Last active
May 12, 2023 05:17
-
-
Save jeremyd2019/cd388a0d7095b72b1f7266275d8d9001 to your computer and use it in GitHub Desktop.
script originally from https://martin.st/temp/pseudo-relocs.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <gmp.h> | |
/* due to https://github.com/msys2/MINGW-packages/issues/15715 | |
* variables/constants are lacking dllimport annotations. But clang/lld are | |
* doing some magic with refptrs that results in a simple access of gmp_version | |
* *not* requiring a pseudo-relocation. This more contrived example results in | |
* a pseudo-relocation on i386, x86_64, and aarch64, with gcc/bfd and clang/lld | |
* (as applicable) */ | |
struct { | |
const char * const * ver; | |
} foo = {&gmp_version}; | |
int main() | |
{ | |
printf("%s\n", *foo.ver); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
nm = 'x86_64-w64-mingw32-nm' | |
addr2line = 'x86_64-w64-mingw32-addr2line' | |
symbol_prefix = '' | |
import subprocess | |
import sys | |
import pefile | |
if len(sys.argv) <= 1: | |
print(sys.argv[0] + " exe") | |
sys.exit(0) | |
exe = sys.argv[1] | |
result = subprocess.run([nm, '-g', '--defined-only', exe], stdout=subprocess.PIPE) | |
symbols = {} | |
addresses = {} | |
for line in result.stdout.decode('utf-8').split('\n'): | |
cols = line.rstrip('\r').split(' ') | |
if len(cols) == 3: | |
sym = cols[2] | |
addr = cols[0] | |
symbols[sym] = addr | |
addr = addr.lstrip('0').lower() | |
if addr in addresses: | |
# Duplicate symbols pointing at the same address; prefer __imp_* | |
if sym.startswith('__imp'): | |
addresses[addr] = sym | |
else: | |
addresses[addr] = sym | |
pe = pefile.PE(exe, fast_load=True) | |
if pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE['IMAGE_FILE_MACHINE_I386']: | |
symbol_prefix = '_' | |
start_sym_name = symbol_prefix + '__RUNTIME_PSEUDO_RELOC_LIST__' | |
end_sym_name = symbol_prefix + '__RUNTIME_PSEUDO_RELOC_LIST_END__' | |
if start_sym_name not in symbols or end_sym_name not in symbols: | |
print("No pseudo reloc symbols") | |
sys.exit(1) | |
base = pe.OPTIONAL_HEADER.ImageBase | |
pseudo_relocs_start = int(symbols[start_sym_name], 16) - base | |
pseudo_relocs_end = int(symbols[end_sym_name], 16) - base | |
# Assuming the modern v2 style pseudo reloc format; skip past 12 byte header. | |
pseudo_relocs_start = pseudo_relocs_start + 12 | |
def resolve(exe, addr): | |
result = subprocess.run([addr2line, '-e', exe, addr], stdout=subprocess.PIPE) | |
lines = result.stdout.decode('utf-8').split('\n') | |
if len(lines) >= 1 and not '?' in lines[0]: | |
return lines[0].strip() | |
return None | |
if pseudo_relocs_start >= pseudo_relocs_end: | |
print("No pseudo relocs") | |
sys.exit(0) | |
pos = pseudo_relocs_start | |
while pos + 12 <= pseudo_relocs_end: | |
sym_addr = pe.get_dword_at_rva(pos) + base | |
sym_addr_str = "%x" % sym_addr | |
reloc_addr = pe.get_dword_at_rva(pos + 4) + base | |
reloc_addr_str = "%#x" % reloc_addr | |
size = pe.get_dword_at_rva(pos + 8) % 256 | |
sym = sym_addr_str | |
if sym_addr_str in addresses: | |
sym = addresses[sym_addr_str] | |
loc = resolve(exe, reloc_addr_str) | |
if loc: | |
loc = ", referenced at " + loc | |
else: | |
loc = "" | |
print("Relocation at " + reloc_addr_str + " targeting " + sym + ", " + str(size) + " bits" + loc) | |
pos += 12 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment