문제

32k 이하로 유지하려는 ARM 프로세서에서 실행할 HEX 파일을 생성하고 있습니다. 그것은 현재 그것보다 훨씬 더 크고 누군가가 그것을 슬림하는 가장 좋은 접근법에 대한 조언을할지 궁금했습니다.

내가 지금까지 한 일은 다음과 같습니다

  1. 그래서 나는 '크기'를 실행하여 16 진 파일의 크기를 결정합니다.
  2. 그런 다음 '크기'다시 각 객체 파일이 링크가 얼마나 큰지 확인하여 16 진 파일을 생성합니다. 크기의 대부분은 외부 라이브러리에서 나온 것 같습니다.
  3. 그런 다음 'readelf'를 사용하여 어떤 기능이 가장 메모리를 차지하는지 확인했습니다.
  4. 코드를 검색하여 해당 기능에 대한 통화를 제거 할 수 있는지 확인했습니다.

여기에 내가 갇히는 곳, 직접 전화하지 않는 기능이 있습니다 (예 : _vfprintf). 전화를 제거 할 수 있도록 전화를 찾을 수 없습니다 (필요하지 않다고 생각하는대로).

그렇다면 다음 단계는 무엇입니까?

답변에 대한 응답 :

  • 내가 볼 수 있듯이 많은 기억을 취하는 기능이 있습니다. 그러나 나는 그것을 부르는 것을 찾을 수 없습니다.
  • 나는 그 기능을 생략하고 싶지만 (가능한 경우) 나는 그것들을 부르는 것을 찾을 수 없다! 내가 추측하는 많은 라이브러리 기능에서 호출 할 수 있습니다.
  • 링커는 원하는대로 작동한다고 생각합니다. 관련 라이브러리 파일 만 포함되어 있습니다. 관련 기능 만 포함되어 있는지 어떻게 알 수 있습니까? 깃발을 설정할 수 있습니까?
  • GCC를 사용하고 있습니다
도움이 되었습니까?

해결책

일반 목록 :

  • 컴파일러 및 링커 디버그 옵션이 비활성화되어 있는지 확인하십시오.
  • 모든 크기 옵션으로 컴파일 및 링크가 켜져 있습니다 (GCC에서 -OS)
  • 운영 strip 실행 파일에서
  • 맵 파일을 생성하고 기능 크기를 확인하십시오. 링커를 가져와 맵 파일을 생성 할 수 있습니다 (-M LD)를 사용할 때, 또는 최종 실행 파일에서 objdump를 사용할 수 있습니다 (이것은 스트립되지 않은 실행 파일에서만 작동합니다!) 실제로 문제를 해결하지는 않지만 최악의 범죄자를 알려줍니다.
  • 사용 nm 각 객체 파일에서 호출 된 기호를 조사합니다. 이것은 당신이 원하지 않는 기능을 호출하는 사람을 찾는 데 도움이 될 것입니다.

원래 질문에는 관련 기능 만 포함하는 것에 대한 하위 질문이있었습니다. gcc 사용되는 모든 객체 파일 내에 모든 기능이 포함됩니다. 다른 방법으로 말하면, 10 개의 함수가 포함 된 객체 파일이있는 경우 1 개의 기능이 실제로 호출 된 경우에도 실행 파일에 모두 포함됩니다.

표준 라이브러리 (예 : LIBC)는 기능을 많은 개별 객체 파일로 분할 한 다음 보관됩니다. 그런 다음 실행 파일은 아카이브에 연결됩니다. 많은 객체 파일로 분할하면 링커는 실제로 호출되는 기능 만 포함 할 수 있습니다. (이것은 당신이 정적으로 연결하고 있다고 가정합니다)

당신이 같은 속임수를 할 수없는 이유는 없습니다. 물론, 당신은 기능을 불러내지 않으면 아마도 직접 제거 할 수 있다고 주장 할 수 있습니다.

다른 라이브러리와 정적으로 연결하는 경우 위에 나열된 도구를 실행하여 비슷한 규칙을 따를 수 있습니다.

다른 팁

작업을 절약 할 수있는 또 다른 최적화는 GCC를 사용하고 있다고 가정 할 때 -ffunction-sections, -wl, -gc- 섹션입니다. 그러나 좋은 도구 체인은 그 말을 할 필요가 없습니다.

설명 : GNU LD 링크 섹션 및 GCC는 다른 말을하지 않는 한 번역 장치 당 한 섹션을 방출합니다. 그러나 C ++에서, 부근 그래프의 노드는 객체와 함수입니다.

향후 참조를 위해 두 번 확인하고 문서화하기 만하면 Thumb 지침을 사용합니까? 그들은 16 개의 비트 버전의 일반 지침입니다. 때로는 26 비트 지침이 필요할 수 있으므로 코드 공간에서 50%를 절약하지 못합니다.

괜찮은 링커는 필요한 기능 만 가져 가야합니다. 그러나 개별 링크에 대한 패키지 기능을 위해 컴파일러 및 Linke 설정이 필요할 수 있습니다.

깊게 포함 된 프로젝트에서는 항상 표준 라이브러리 기능을 사용하지 않으려 고 노력합니다. "strtol ()"과 같은 간단한 기능조차 이진 크기를 폭파시킵니다. 가능하다면 그 전화를 피하십시오.

가장 깊이 내장 된 프로젝트에서는 다양한 "printf ()"또는 동적 메모리 할당이 필요하지 않습니다 (많은 컨트롤러에는 32KB 이하의 RAM이 있습니다).

"printf ()"을 사용하는 대신 매우 간단한 사용자 정의 "printf ()"을 사용하는 대신이 함수는 숫자가 16 진수 또는 십진 형식으로 만 인쇄 할 수 있습니다. 대부분의 데이터 구조는 컴파일 타임에 PrealLocated입니다.

결국 나는 프로젝트를 가장 간단한 형태로 줄인 다음 제거하려는 기능이 'readelf'파일에 나타날 때까지 파일을 천천히 추가했습니다. 그런 다음 파일을 가졌을 때 모든 것을 댓글을 달고 함수가 다시 나타날 때까지 천천히 물건을 추가했습니다. 그래서 결국 나는 그것을 불렀던 것을 발견하고 그 모든 전화를 제거했습니다 ... 이제 그것은 원하는대로 작동합니다 ... 달콤합니다!

그래도 더 나은 방법이어야합니다.

Andrew Edgecombe는 훌륭한 목록을 가지고 있지만 마지막 바이트를 실제로 긁어 내고 싶다면 sstrip 목록에서 누락되어 KB를 몇 개 더 면도 할 수있는 좋은 도구입니다.

예를 들어, 실행할 때 strip 그 자체, ~ 2kb를 면도 할 수 있습니다.

오래된 readme에서 (상단의 댓글 참조 이것 간접 소스 파일) :

SSTRIP는 프로그램의 메모리 이미지의 일부가 아닌 ELF 파일의 끝에서 내용을 제거하는 작은 유틸리티입니다.

대부분의 ELF 실행 파일은 프로그램 헤더 테이블과 섹션 헤더 테이블 모두로 제작되었습니다. 그러나 OS가 프로그램을로드, 링크 및 실행하려면 전자 만 필요합니다. SSTRIP는 ELF 헤더, 프로그램 헤더 테이블 및 그 내용을 추출하여 다른 모든 것을 비트 버킷에 남겨 두려고 시도합니다. 저장할 부품 후에는 마지막에 발생하는 파일의 일부만 제거 할 수 있습니다. 그러나 여기에는 거의 항상 섹션 헤더 테이블이 포함되며 때로는 프로그램을 실행할 때 사용되지 않는 몇 개의 임의 섹션이 포함됩니다.

제거하는 일부 정보로 인해 SStrip'd 실행 파일은 문제가 있다는 소문 일부 도구로. 이것은 소스의 의견에서 더 많이 논의됩니다.

또한 ... 가장 작은 실행 파일을 만드는 방법에 대한 재미있는/미친 책을 읽으십시오. 이 기사 읽을 가치가 있습니다.

이 특정 요구에 답하기 위해 :

• 그 기능을 생략하고 싶지만 (가능하다면), 나는 그것들을 부르는 것을 찾을 수 없습니다 !! 내가 추측하는 많은 라이브러리 기능에서 호출 할 수 있습니다.

코드 기반을 분석하여 누가 주어진 기능을 호출하는지, 그와 같은 것을 호출하는지 확인하려면 Scitools가 제공 한 "이해 C"라는 훌륭한 도구가 있습니다.

https://scitools.com/

나는 과거에 정적 코드 분석을 수행하기 위해 자주 사용했습니다. 라이브러리 종속성 트리를 결정하는 데 실제로 도움이 될 수 있습니다. 그것은 무엇보다도 호출 트리를 쉽게 위아래로 탐색 할 수 있습니다.

제한된 시간 평가를 제공하면 라이센스를 구매해야합니다.

당신은 같은 것을 볼 수 있습니다 실행 가능한 압축.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top