예를 들어 다음과 같은 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
.objcopy
readelf
답변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 감사합니다.