objdump에서 16진수 출력만 가져오기

objdump에서 16진수 출력만 가져오기

예를 들어 다음과 같은 C 함수가 있습니다.

void f(int *x, int *y)
{
    (*x) = (*x) * (*y);
}

에 저장하면 다음과 같은 f.c컴파일 gcc -c f.c결과가 나타납니다 f.o.objdump -d f.o

f.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <f>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 89 7d f8             mov    %rdi,-0x8(%rbp)
   8:   48 89 75 f0             mov    %rsi,-0x10(%rbp)
   c:   48 8b 45 f8             mov    -0x8(%rbp),%rax
  10:   8b 10                   mov    (%rax),%edx
  12:   48 8b 45 f0             mov    -0x10(%rbp),%rax
  16:   8b 00                   mov    (%rax),%eax
  18:   0f af d0                imul   %eax,%edx
  1b:   48 8b 45 f8             mov    -0x8(%rbp),%rax
  1f:   89 10                   mov    %edx,(%rax)
  21:   5d                      pop    %rbp
  22:   c3                      retq  

나는 이것이 다음과 같이 출력되기를 원합니다.

55 48 89 e5 48 89 7d f8 48 89 75 f0 48 8b 45 f8 8b 10 48 8b 45 f0 8b 00 0f af d0 48 8b 45 f8 89 10 5d c3

즉, 함수의 16진수 값입니다. objdump이를 수행할 수 있는 플래그 가 있습니까 ? 그렇지 않으면 원하는 출력을 얻기 위해 어떤 도구(예: awk, sed, cut 등)를 사용할 수 있습니까?

답변1

다음 명령을 사용하여 텍스트 세그먼트의 바이트 값을 추출할 수 있습니다.

$ objcopy -O binary -j .text f.o fo

-O 바이너리 옵션:

objcopy는 바이너리 출력 대상(예: -O 바이너리 사용)을 사용하여 원시 바이너리를 생성하는 데 사용할 수 있습니다. objcopy가 원시 바이너리 파일을 생성할 때 기본적으로 입력 개체 파일 내용의 메모리 덤프를 생성합니다. 모든 기호 및 재배치 정보는 삭제됩니다. 메모리 덤프는 출력 파일의 가장 낮은 부분에 복사된 로드 주소부터 시작됩니다.

옵션 -j .text:

-jsectionpattern
--only-section=sectionpattern
입력 파일에서 지정된 섹션만 출력 파일에 복사합니다. 이 옵션은 여러 번 주어질 수 있습니다.
이 옵션을 부적절하게 사용하면 출력 파일을 사용할 수 없게 될 수도 있습니다. 섹션 패턴에는 와일드카드가 허용됩니다.

최종 결과는 fo해당 섹션의 바이너리 값 .text, 즉 기호나 재배치 정보가 없는 실행 코드만 포함하는 파일( )입니다.

그런 다음 fo파일의 16진수 값을 인쇄합니다.

$ od -An -v -t x1 fo
 55 48 89 e5 48 89 7d f8 48 89 75 f0 48 8b 45 f8
 8b 10 48 8b 45 f0 8b 00 0f af d0 48 8b 45 f8 89
 10 90 5d c3

답변2

어때요?

awk '/^....:/{a=substr($0,9,20);sub(/ +$/,"",a);b=b" "a}END{print substr(b,2)}'

이 경우에는 반환됩니다.

55 48 89 e5 48 89 7d f8 48 89 75 f0 48 8b 45 f8 8b 10 48 8b 45 f0 8b 00 0f af d0 48 8b 45 f8 89 10 5d c3

답변3

또 다른 옵션은 다음을 사용하는 것입니다 readelf.

$ readelf -x .text f.o

Hex dump of section '.text':
  0x00070c00 f30f1efa 488d15fd 13100048 8d357606 ....H......H.5v.
  0x00070c10 1100488d 3dc33809 00e902f5 fffff30f ..H.=.8.........
  0x00070c20 1efa5548 8d2d9606 1100be22 00000045 ..UH.-....."...E
  ...

일부 특정 .elf 파일의 경우 알 수 없는 이유로(특정 아키텍처 비호환성으로 인해) 누락되었으며 제가 찾을 수 있는 유일한 작동 솔루션 입니다 objdump.objcopyreadelf

답변4

해결 방법 1:

42sh$ objcopy -j .text f.o /proc/self/fd/1 -O verilog | tail -n +2 | tr '\n' ' ' | tr -d '\r'
8B 07 0F AF 06 89 07 C3 42sh$

'\n'이 공백으로 변환되어 마지막 개행 문자 대신 후행 공백이 표시되는 것을 볼 수 있습니다. tail과 tr은 원하는 것을 정확하게 변환하는 데에만 사용됩니다.

해결 방법 2:

42sh$ objcopy -O binary -j .text f.o /proc/self/fd/1 | xxd -ps -c 36 | sed 's,..,& ,g; s, $,,'
8b 07 0f af 06 89 07 c3
42sh$

여기에서는 objcopy에 원시 바이너리로 인쇄하도록 요청한 다음 허용된 답변과 같이 od(8진수 덤프를 나타냄) 대신 xxd(16진수 덤프를 나타냄)로 16진수 인코딩합니다.

-c는 문자 수입니다. 모든 기호를 한 줄에 표시하려면 큰 숫자를 사용할 수 있습니다. sed는 설명된 대로 두 가지 대체 항목을 사용합니다.https://askubuntu.com/a/661687/772955하나는 공백을 펼치는 것이고 다른 하나는 마지막 공백을 제거하는 것입니다. sed가 예약되었습니다.\n

일반적인 설명:

objcopy는 우리가 원하는 부분만 읽습니다.

두 솔루션 모두 Linux에서는 /proc/self/fd/1, darwin에서는 /dev/fd/1을 가리키는 /dev/stdout 파이프에 직접 작성하여 임시 파일을 방지합니다.

2진수 출력이라면 16진수로 변환해야 합니다.

그런 다음 sed/tr을 사용하여 아름답게 만들고 awk/perl을 사용할 수 있습니다.

편집 1:

@Stéphane Chazelas 감사합니다.

관련 정보