请参阅以下objdump
特定功能的特定目标文件的行(func
):
3c: e03a b.n 78
现在,e03a
目标系统(ARMv6-M)中的操作码显示跳转到的位置PC + 0x78
。正确的解释是:
3c: e03a b.n B4
每个其他函数和文件都包含正确的b.n
解释,并在其objdump
转储中包含正确的值计算。由于某些原因,仅此功能会导致objdump
“混淆”。
注意:func
从开始0x0
。
我无法想到这种情况的任何原因。而且由于我具有解析和使用objdump
转储的工具,因此这对我造成了很大的问题。有什么合理的理由吗?
工具链: gcc-arm-none-eabi-4_9-2015q3
运行此工具链的平台: Ubuntu 16.04.2 LTS
编辑:我附加部分转储:
Disassembly of section i.func: 00000000: 0: b531 push {r0, r4, r5, lr} 2: b088 sub sp, #32 4: 2100 movs r1, #0 6: 9106 str r1, [sp, #24] 8: 482c ldr r0, [pc, #176] ; (bc ) a: 6800 ldr r0, [r0, #0] c: 6840 ldr r0, [r0, #4] e: 9103 str r1, [sp, #12] 10: 1c40 adds r0, r0, #1 12: 9002 str r0, [sp, #8] 14: 492a ldr r1, [pc, #168] ; (c0 ) 16: 2000 movs r0, #0 18: 9104 str r1, [sp, #16] 1a: 9005 str r0, [sp, #20] 1c: a802 add r0, sp, #8 1e: f7ff fffe bl 0 22: f7ff fffe bl 0 26: 4604 mov r4, r0 28: 4d26 ldr r5, [pc, #152] ; (c4 ) 2a: 42ac cmp r4, r5 2c: d007 beq.n 3e 2e: a326 add r3, pc, #152 ; (adr r3, c8 ) 30: 22ee movs r2, #238 ; 0xee 32: 492c ldr r1, [pc, #176] ; (e4 ) 34: 2000 movs r0, #0 36: 9400 str r4, [sp, #0] 38: f7ff fffe bl 0 3c: e03a b.n 78 <---- PROBLEM IS HERE 3e: f7ff fffe bl 0 42: 9006 str r0, [sp, #24] 44: f3bf 8f5f dmb sy 48: a808 add r0, sp, #32 4a: 7800 ldrb r0, [r0, #0] 4c: 2800 cmp r0, #0 4e: d00f beq.n 70 50: 9806 ldr r0, [sp, #24] 52: 2803 cmp r0, #3 54: d016 beq.n 84 56: f7ff fffe bl 0 5a: 4604 mov r4, r0 5c: 42ac cmp r4, r5 5e: d01a beq.n 96 60: a321 add r3, pc, #132 ; (adr r3, e8 ) 62: 22fa movs r2, #250 ; 0xfa 64: 491f ldr r1, [pc, #124] ; (e4 ) 66: 2000 movs r0, #0 68: 9400 str r4, [sp, #0] 6a: f7ff fffe bl 0 6e: e021 b.n 46 <--- ALSO HERE SAME PROBLEM 70: f7ff fffe bl 0 74: 2800 cmp r0, #0 76: d003 beq.n 80 78: a808 add r0, sp, #32 7a: 7800 ldrb r0, [r0, #0] 7c: 2800 cmp r0, #0 7e: d018 beq.n b2 80: f7ff fffe bl 0 84: f7ff fffe bl 0 88: 2800 cmp r0, #0 8a: d002 beq.n 92 8c: 9806 ldr r0, [sp, #24] 8e: 2803 cmp r0, #3 90: d00f beq.n b2 92: f7ff fffe bl 0 96: f7ff fffe bl 0 9a: 4604 mov r4, r0 9c: 42ac cmp r4, r5 9e: d008 beq.n b2 a0: 22ff movs r2, #255 ; 0xff a2: a318 add r3, pc, #96 ; (adr r3, 104 ) a4: 3201 adds r2, #1 a6: 490f ldr r1, [pc, #60] ; (e4 ) a8: 2000 movs r0, #0 aa: 9400 str r4, [sp, #0] ac: f7ff fffe bl 0 b0: e000 b.n b4 b2: 462c mov r4, r5 b4: 4620 mov r0, r4
Ctx.. 6
看起来像个虫子;每次在两次跳转之间跳转时,都需要像这里一样进行重新定位
38: f7ff fffe bl 03c: e03a b.n 78 <---- PROBLEM IS HERE 3e: f7ff fffe bl 0
或在这里
6a: f7ff fffe bl 06e: e021 b.n 46 70: f7ff fffe bl 0
计算错误。
没有正当的理由;向错误跟踪系统http://www.sourceware.org/bugzilla/的报告可能是适当的(在验证后,最新版本也受到此错误的影响)
编辑:我有一些时间深入研究此错误。
的问题是,如果该指令之前的b.n
任何32位指令和该指令之后的b.n
受搬迁,objdump的错误地假定该b.n
指令具有与它和套的相对pc用于偏移计算相关联的为0的重定位。
该代码部分来自binutils/objdump.c
罪魁祸首:
bfd_signed_vma distance_to_rel; distance_to_rel = (**relppp)->address - (rel_offset + addr_offset); /* Check to see if the current reloc is associated with the instruction that we are about to disassemble. */ if (distance_to_rel == 0 /* FIXME: This is wrong. We are trying to catch relocs that are addressed part way through the current instruction, as might happen with a packed VLIW instruction. Unfortunately we do not know the length of the current instruction since we have not disassembled it yet. Instead we take a guess based upon the length of the previous instruction. The proper solution is to have a new target-specific disassembler function which just returns the length of an instruction at a given address without trying to display its disassembly. */ || (distance_to_rel > 0 && distance_to_rel <(bfd_signed_vma) (previous_octets/ opb))) { inf->flags |= INSN_HAS_RELOC; aux->reloc = **relppp; }
注释说明了一切:该解析器从上一条32位指令中猜测,下一条指令也是 32位(不是!)。重定位是针对的3e
,反汇编器假定下一条指令是从3c
到3f
,因此将b.n
标记为INSN_HAS_RELOC
,从而导致错误的偏移量计算。看起来,这样很难解决。
但是,您可以尝试像这样修补objdump:
if (distance_to_rel == 0) { inf->flags |= INSN_HAS_RELOC; aux->reloc = **relppp; }
反之,这可能会产生误差,但是这种情况很少见,也许您会更好。
看起来像个虫子;每次在两次跳转之间跳转时,都需要像这里一样进行重新定位
38: f7ff fffe bl 03c: e03a b.n 78 <---- PROBLEM IS HERE 3e: f7ff fffe bl 0
或在这里
6a: f7ff fffe bl 06e: e021 b.n 46 70: f7ff fffe bl 0
计算错误。
没有正当的理由;向错误跟踪系统http://www.sourceware.org/bugzilla/的报告可能是适当的(在验证后,最新版本也受到此错误的影响)
编辑:我有一些时间深入研究此错误。
的问题是,如果该指令之前的b.n
任何32位指令和该指令之后的b.n
受搬迁,objdump的错误地假定该b.n
指令具有与它和套的相对pc用于偏移计算相关联的为0的重定位。
该代码部分来自binutils/objdump.c
罪魁祸首:
bfd_signed_vma distance_to_rel; distance_to_rel = (**relppp)->address - (rel_offset + addr_offset); /* Check to see if the current reloc is associated with the instruction that we are about to disassemble. */ if (distance_to_rel == 0 /* FIXME: This is wrong. We are trying to catch relocs that are addressed part way through the current instruction, as might happen with a packed VLIW instruction. Unfortunately we do not know the length of the current instruction since we have not disassembled it yet. Instead we take a guess based upon the length of the previous instruction. The proper solution is to have a new target-specific disassembler function which just returns the length of an instruction at a given address without trying to display its disassembly. */ || (distance_to_rel > 0 && distance_to_rel <(bfd_signed_vma) (previous_octets/ opb))) { inf->flags |= INSN_HAS_RELOC; aux->reloc = **relppp; }
注释说明了一切:该解析器从上一条32位指令中猜测,下一条指令也是 32位(不是!)。重定位是针对的3e
,反汇编器假定下一条指令是从3c
到3f
,因此将b.n
标记为INSN_HAS_RELOC
,从而导致错误的偏移量计算。看起来,这样很难解决。
但是,您可以尝试像这样修补objdump:
if (distance_to_rel == 0) { inf->flags |= INSN_HAS_RELOC; aux->reloc = **relppp; }
反之,这可能会产生误差,但是这种情况很少见,也许您会更好。