Crashlog: Handle image relocation in MinGW BFD symbol lookup
This commit is contained in:
@@ -1249,13 +1249,13 @@ static void find_address_in_section(bfd *abfd, asection *section, void *data)
|
|||||||
|
|
||||||
if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0) return;
|
if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0) return;
|
||||||
|
|
||||||
|
bfd_vma addr = info->addr + info->image_base;
|
||||||
bfd_vma vma = bfd_get_section_vma(abfd, section);
|
bfd_vma vma = bfd_get_section_vma(abfd, section);
|
||||||
if (info->addr < vma) return;
|
|
||||||
|
|
||||||
bfd_size_type size = get_bfd_section_size(abfd, section);
|
bfd_size_type size = get_bfd_section_size(abfd, section);
|
||||||
if (info->addr >= vma + size) return;
|
|
||||||
|
|
||||||
info->found = bfd_find_nearest_line(abfd, section, info->syms, info->addr - vma,
|
if (addr < vma || addr >= vma + size) return;
|
||||||
|
|
||||||
|
info->found = bfd_find_nearest_line(abfd, section, info->syms, addr - vma,
|
||||||
&(info->file_name), &(info->function_name), &(info->line));
|
&(info->file_name), &(info->function_name), &(info->line));
|
||||||
|
|
||||||
if (info->found && info->function_name) {
|
if (info->found && info->function_name) {
|
||||||
@@ -1266,7 +1266,7 @@ static void find_address_in_section(bfd *abfd, asection *section, void *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (info->found) {
|
} else if (info->found) {
|
||||||
bfd_vma target = info->addr - vma;
|
bfd_vma target = addr - vma;
|
||||||
bfd_vma best_diff = size;
|
bfd_vma best_diff = size;
|
||||||
for (long i = 0; i < info->sym_count; i++) {
|
for (long i = 0; i < info->sym_count; i++) {
|
||||||
asymbol *sym = info->syms[i];
|
asymbol *sym = info->syms[i];
|
||||||
@@ -1302,11 +1302,34 @@ void lookup_addr_bfd(const char *obj_file_name, sym_bfd_obj_cache &bfdc, sym_inf
|
|||||||
if (obj.sym_count <= 0) return;
|
if (obj.sym_count <= 0) return;
|
||||||
|
|
||||||
obj.usable = true;
|
obj.usable = true;
|
||||||
|
|
||||||
|
#if defined(__MINGW32__)
|
||||||
|
/* Handle Windows PE relocation.
|
||||||
|
* libbfd sections (and thus symbol addresses) are relative to the image base address (i.e. absolute).
|
||||||
|
* Due to relocation/ASLR/etc the module base address in memory may not match the image base address.
|
||||||
|
* Instead of using the absolute addresses, expect the inputs here to be relative to the module base address
|
||||||
|
* in memory, which is easy to get.
|
||||||
|
* The original image base address is very awkward to get, but as it's always the same, just hard-code it
|
||||||
|
* via the expected .text section address here. */
|
||||||
|
#ifdef _M_AMD64
|
||||||
|
asection *section = bfd_get_section_by_name(obj.abfd, ".text");
|
||||||
|
if (section != nullptr && section->vma == 0x140001000) {
|
||||||
|
obj.image_base = 0x140000000;
|
||||||
|
}
|
||||||
|
#elif defined(_M_IX86)
|
||||||
|
asection *section = bfd_get_section_by_name(obj.abfd, ".text");
|
||||||
|
if (section != nullptr && section->vma == 0x401000) {
|
||||||
|
obj.image_base = 0x400000;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (obj.image_base == 0) obj.usable = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!obj.usable) return;
|
if (!obj.usable) return;
|
||||||
|
|
||||||
info.abfd = obj.abfd;
|
info.abfd = obj.abfd;
|
||||||
|
info.image_base = obj.image_base;
|
||||||
info.syms = obj.syms;
|
info.syms = obj.syms;
|
||||||
info.sym_count = obj.sym_count;
|
info.sym_count = obj.sym_count;
|
||||||
|
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
struct sym_bfd_obj {
|
struct sym_bfd_obj {
|
||||||
bfd *abfd = nullptr;
|
bfd *abfd = nullptr;
|
||||||
|
bfd_vma image_base = 0;
|
||||||
asymbol **syms = nullptr;
|
asymbol **syms = nullptr;
|
||||||
const char *file_name = nullptr;
|
const char *file_name = nullptr;
|
||||||
long sym_count = 0;
|
long sym_count = 0;
|
||||||
@@ -50,6 +51,7 @@ struct sym_bfd_obj_cache {
|
|||||||
struct sym_info_bfd {
|
struct sym_info_bfd {
|
||||||
bfd_vma addr;
|
bfd_vma addr;
|
||||||
bfd *abfd;
|
bfd *abfd;
|
||||||
|
bfd_vma image_base = 0;
|
||||||
asymbol **syms;
|
asymbol **syms;
|
||||||
long sym_count;
|
long sym_count;
|
||||||
const char *file_name;
|
const char *file_name;
|
||||||
|
@@ -427,12 +427,14 @@ static const uint MAX_FRAMES = 64;
|
|||||||
/* Get module name. */
|
/* Get module name. */
|
||||||
const char *mod_name = "???";
|
const char *mod_name = "???";
|
||||||
const char *image_name = nullptr;
|
const char *image_name = nullptr;
|
||||||
|
DWORD64 image_base = 0;
|
||||||
|
|
||||||
IMAGEHLP_MODULE64 module;
|
IMAGEHLP_MODULE64 module;
|
||||||
module.SizeOfStruct = sizeof(module);
|
module.SizeOfStruct = sizeof(module);
|
||||||
if (proc.pSymGetModuleInfo64(hCur, frame.AddrPC.Offset, &module)) {
|
if (proc.pSymGetModuleInfo64(hCur, frame.AddrPC.Offset, &module)) {
|
||||||
mod_name = module.ModuleName;
|
mod_name = module.ModuleName;
|
||||||
image_name = module.ImageName;
|
image_name = module.ImageName;
|
||||||
|
image_base = module.BaseOfImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print module and instruction pointer. */
|
/* Print module and instruction pointer. */
|
||||||
@@ -452,7 +454,7 @@ static const uint MAX_FRAMES = 64;
|
|||||||
} else if (image_name != nullptr) {
|
} else if (image_name != nullptr) {
|
||||||
#if defined (WITH_BFD)
|
#if defined (WITH_BFD)
|
||||||
/* subtract one to get the line before the return address, i.e. the function call line */
|
/* subtract one to get the line before the return address, i.e. the function call line */
|
||||||
sym_info_bfd bfd_info(static_cast<bfd_vma>(frame.AddrPC.Offset) - 1);
|
sym_info_bfd bfd_info(static_cast<bfd_vma>(frame.AddrPC.Offset) - static_cast<bfd_vma>(image_base) - 1);
|
||||||
lookup_addr_bfd(image_name, bfd_cache, bfd_info);
|
lookup_addr_bfd(image_name, bfd_cache, bfd_info);
|
||||||
if (bfd_info.function_name != nullptr) {
|
if (bfd_info.function_name != nullptr) {
|
||||||
const char *func_name = bfd_info.function_name;
|
const char *func_name = bfd_info.function_name;
|
||||||
|
Reference in New Issue
Block a user