Changes to handle elf image bases / text link-at addresses (#21)
Figure out the text offset for elf files. When testing on a system that did not use ASLR by default a user found addr2line being invoked with the wrong addresses.
This commit is contained in:
parent
d589f2a609
commit
72228ab5e8
@ -250,6 +250,7 @@ static_assert(n_digits(10) == 2, "n_digits utility producing the wrong result");
|
||||
static_assert(n_digits(11) == 2, "n_digits utility producing the wrong result");
|
||||
static_assert(n_digits(1024) == 4, "n_digits utility producing the wrong result");
|
||||
|
||||
// TODO: Re-evaluate use of off_t
|
||||
template<typename T, typename std::enable_if<std::is_pod<T>::value, int>::type = 0>
|
||||
T load_bytes(FILE* obj_file, off_t offset) {
|
||||
T object;
|
||||
|
||||
87
src/platform/elf.hpp
Normal file
87
src/platform/elf.hpp
Normal file
@ -0,0 +1,87 @@
|
||||
#ifndef ELF_HPP
|
||||
#define ELF_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#if IS_LINUX
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include <elf.h>
|
||||
|
||||
template<typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
|
||||
T elf_byteswap_if_needed(T value, bool elf_is_little) {
|
||||
if(is_little_endian() == elf_is_little) {
|
||||
return value;
|
||||
} else {
|
||||
return byteswap(value);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Re-evaluate use of off_t
|
||||
// I think we can rely on PT_PHDR https://stackoverflow.com/q/61568612/15675011...
|
||||
static uintptr_t elf_get_module_image_base_from_program_table(
|
||||
FILE* file,
|
||||
bool is_64,
|
||||
bool is_little_endian,
|
||||
off_t e_phoff,
|
||||
off_t e_phentsize,
|
||||
int e_phnum
|
||||
) {
|
||||
for(int i = 0; i < e_phnum; i++) {
|
||||
if(is_64) {
|
||||
Elf64_Phdr program_header = load_bytes<Elf64_Phdr>(file, e_phoff + e_phentsize * i);
|
||||
if(elf_byteswap_if_needed(program_header.p_type, is_little_endian) == PT_PHDR) {
|
||||
return elf_byteswap_if_needed(program_header.p_vaddr, is_little_endian)
|
||||
- elf_byteswap_if_needed(program_header.p_offset, is_little_endian);
|
||||
}
|
||||
} else {
|
||||
Elf32_Phdr program_header = load_bytes<Elf32_Phdr>(file, e_phoff + e_phentsize * i);
|
||||
if(elf_byteswap_if_needed(program_header.p_type, is_little_endian) == PT_PHDR) {
|
||||
return elf_byteswap_if_needed(program_header.p_vaddr, is_little_endian)
|
||||
- elf_byteswap_if_needed(program_header.p_offset, is_little_endian);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uintptr_t elf_get_module_image_base(const std::string& obj_path) {
|
||||
FILE* file = fopen(obj_path.c_str(), "rb");
|
||||
// Initial checks/metadata
|
||||
auto magic = load_bytes<std::array<char, 4>>(file, 0);
|
||||
internal_verify(magic == (std::array<char, 4>{0x7F, 'E', 'L', 'F'}));
|
||||
bool is_64 = load_bytes<uint8_t>(file, 4) == 2;
|
||||
bool is_little_endian = load_bytes<uint8_t>(file, 5) == 1;
|
||||
internal_verify(load_bytes<uint8_t>(file, 6) == 1, "Unexpected ELF version");
|
||||
//
|
||||
if(is_64) {
|
||||
Elf64_Ehdr file_header = load_bytes<Elf64_Ehdr>(file, 0);
|
||||
internal_verify(file_header.e_ehsize == sizeof(Elf64_Ehdr));
|
||||
return elf_get_module_image_base_from_program_table(
|
||||
file,
|
||||
is_64,
|
||||
is_little_endian,
|
||||
elf_byteswap_if_needed(file_header.e_phoff, is_little_endian),
|
||||
elf_byteswap_if_needed(file_header.e_phentsize, is_little_endian),
|
||||
elf_byteswap_if_needed(file_header.e_phnum, is_little_endian)
|
||||
);
|
||||
} else {
|
||||
Elf32_Ehdr file_header = load_bytes<Elf32_Ehdr>(file, 0);
|
||||
internal_verify(file_header.e_ehsize == sizeof(Elf32_Ehdr));
|
||||
return elf_get_module_image_base_from_program_table(
|
||||
file,
|
||||
is_64,
|
||||
is_little_endian,
|
||||
elf_byteswap_if_needed(file_header.e_phoff, is_little_endian),
|
||||
elf_byteswap_if_needed(file_header.e_phentsize, is_little_endian),
|
||||
elf_byteswap_if_needed(file_header.e_phnum, is_little_endian)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -1,13 +1,13 @@
|
||||
#ifndef MACHO_HPP
|
||||
#define MACHO_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#if IS_APPLE
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#include <mach-o/loader.h>
|
||||
#include <mach-o/swap.h>
|
||||
#include <mach-o/fat.h>
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
#ifndef PE_HPP
|
||||
#define PE_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#if IS_WINDOWS
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#if IS_WINDOWS
|
||||
#include <windows.h>
|
||||
|
||||
template<typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
|
||||
|
||||
@ -21,6 +21,8 @@
|
||||
#include <sys/wait.h>
|
||||
#if IS_APPLE
|
||||
#include "../platform/mach-o.hpp"
|
||||
#else
|
||||
#include "../platform/elf.hpp"
|
||||
#endif
|
||||
#elif IS_WINDOWS
|
||||
#include "../platform/pe.hpp"
|
||||
@ -166,8 +168,7 @@ namespace cpptrace {
|
||||
|
||||
#if !IS_APPLE
|
||||
uintptr_t get_module_image_base(const dlframe &entry) {
|
||||
(void)entry;
|
||||
return 0;
|
||||
return elf_get_module_image_base(entry.obj_path);
|
||||
}
|
||||
#else
|
||||
uintptr_t get_module_image_base(const dlframe &entry) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user