Snaipe / Mimick

A KISS, cross-platform C mocking library
MIT License
152 stars 43 forks source link

Tests fail on Ubuntu 20.04 aarch64 #9

Closed hidmic closed 4 years ago

hidmic commented 4 years ago

System details

Bug report

Tests fail because Mimick fails to inject the mock in the right place. ELF support first checks for the fn_vv symbol in the .rela.dyn section and only goes look for it in the .rela.plt section if it fails the first lookup. I can see the mmk_test executable shows two relocations for that symbol, one in each table.

Relocation section '.rela.dyn' at offset 0x1670 contains 24 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
...
000000022f60  000900000401 R_AARCH64_GLOB_DA 0000000000000000 fn_vv + 0
...
000000022f78  000c00000401 R_AARCH64_GLOB_DA 0000000000000000 fn_ii + 0
000000022f80  000d00000401 R_AARCH64_GLOB_DA 0000000000000000 fn_ii_va + 0
...
Relocation section '.rela.plt' at offset 0x18b0 contains 18 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
...
000000023020  000900000402 R_AARCH64_JUMP_SL 0000000000000000 fn_vv + 0
000000023030  000c00000402 R_AARCH64_JUMP_SL 0000000000000000 fn_ii + 0
000000023038  000d00000402 R_AARCH64_JUMP_SL 0000000000000000 fn_ii_va + 0
...

Stepping through machine code, I can see Mimick puts the mock trampoline in the GOT but trampolines in code use the PLT's GOT.

Discussion

I failed to find a concise and complete explanation out there as to why two relocations are showing in my aarch64 box. My recollection so far is that, in the most general case, a dynamic ELF executable needs both an R_<ARCH>_JUMP_SLOT relocation in the .rela.plt section for lazy binding of an external callable symbol and an R_<ARCH>_GLOB_DAT relocation in the .rela.dyn section when/if the address of an external callable symbol is requested (i.e. the function pointer). And while some linkers may perform an optimization and deduplicate this information, they are not bound to do so.

@Snaipe does that sound reasonable? I can see plt_get_offsets() is capable of returning multiple offsets. Did you intend to support such cases?