|
21 | 21 | // SOFTWARE. |
22 | 22 |
|
23 | 23 | #include "elf_parser.hpp" |
| 24 | +#include <sys/stat.h> |
| 25 | +#include <cstring> |
24 | 26 | using namespace elf_parser; |
25 | 27 |
|
26 | 28 | std::vector<section_t> Elf_parser::get_sections() { |
@@ -80,23 +82,53 @@ std::vector<symbol_t> Elf_parser::get_symbols() { |
80 | 82 | // get headers for offsets |
81 | 83 | Elf64_Ehdr *ehdr = (Elf64_Ehdr*)m_mmap_program; |
82 | 84 | Elf64_Shdr *shdr = (Elf64_Shdr*)(m_mmap_program + ehdr->e_shoff); |
83 | | - |
| 85 | + // get build-id |
| 86 | + char *build_id_buf = nullptr; |
| 87 | + std::string buildId; |
84 | 88 | // get strtab |
85 | 89 | char *sh_strtab_p = nullptr; |
86 | | - for(auto &sec: secs) { |
87 | | - if((sec.section_type == "SHT_STRTAB") && (sec.section_name == ".strtab")){ |
88 | | - sh_strtab_p = (char*)m_mmap_program + sec.section_offset; |
89 | | - break; |
90 | | - } |
91 | | - } |
92 | | - |
93 | 90 | // get dynstr |
94 | 91 | char *sh_dynstr_p = nullptr; |
95 | | - for(auto &sec: secs) { |
96 | | - if((sec.section_type == "SHT_STRTAB") && (sec.section_name == ".dynstr")){ |
97 | | - sh_dynstr_p = (char*)m_mmap_program + sec.section_offset; |
98 | | - break; |
| 92 | + for (auto &sec : secs) { |
| 93 | + if ((sec.section_type == "SHT_NOTE") && |
| 94 | + (sec.section_name == ".note.gnu.build-id")) { |
| 95 | + build_id_buf = |
| 96 | + reinterpret_cast<char *>(m_mmap_program) + sec.section_offset; |
| 97 | + |
| 98 | + Elf64_Nhdr *nhdr64 = reinterpret_cast<Elf64_Nhdr *>(build_id_buf); |
| 99 | + |
| 100 | + uint64_t n_namesz = nhdr64->n_namesz; |
| 101 | + uint64_t n_descsz = nhdr64->n_descsz; |
| 102 | + uint64_t n_type = nhdr64->n_type; |
| 103 | + char *n_data = build_id_buf + sizeof(Elf64_Nhdr); |
| 104 | + |
| 105 | + if (std::strcmp(n_data, ELF_NOTE_GNU) == 0 && |
| 106 | + n_type == NT_GNU_BUILD_ID) { |
| 107 | + const char *hex_digits = "0123456789abcdef"; |
| 108 | + unsigned char *build_id; |
| 109 | + |
| 110 | + build_id = (unsigned char *)n_data + n_namesz; |
| 111 | + for (int i = 0; i < n_descsz; i++) { |
| 112 | + buildId.push_back(hex_digits[(build_id[i] >> 4) & 0xf]); |
| 113 | + buildId.push_back(hex_digits[(build_id[i] >> 0) & 0xf]); |
| 114 | + } |
99 | 115 | } |
| 116 | + } |
| 117 | + |
| 118 | + if ((sec.section_type == "SHT_STRTAB") && |
| 119 | + (sec.section_name == ".strtab")) { |
| 120 | + sh_strtab_p = |
| 121 | + reinterpret_cast<char *>(m_mmap_program) + sec.section_offset; |
| 122 | + } |
| 123 | + |
| 124 | + if ((sec.section_type == "SHT_STRTAB") && |
| 125 | + (sec.section_name == ".dynstr")) { |
| 126 | + sh_dynstr_p = |
| 127 | + reinterpret_cast<char *>(m_mmap_program) + sec.section_offset; |
| 128 | + } |
| 129 | + if (build_id_buf && sh_strtab_p && sh_dynstr_p) { |
| 130 | + break; |
| 131 | + } |
100 | 132 | } |
101 | 133 |
|
102 | 134 | std::vector<symbol_t> symbols; |
@@ -127,6 +159,23 @@ std::vector<symbol_t> Elf_parser::get_symbols() { |
127 | 159 | symbols.push_back(symbol); |
128 | 160 | } |
129 | 161 | } |
| 162 | + |
| 163 | + if (buildId.length() > 0) { |
| 164 | + /* Look for separate debug info: build-ids */ |
| 165 | + std::string debug_file = |
| 166 | + std::string("/usr/lib/debug/.build-id/" + buildId.substr(0, 2) + "/" + |
| 167 | + buildId.substr(2, std::string::npos) + ".debug"); |
| 168 | + |
| 169 | + if (m_program_path != debug_file) { |
| 170 | + struct stat buffer; |
| 171 | + if (stat(debug_file.c_str(), &buffer) == 0) { |
| 172 | + Elf_parser dp(debug_file.c_str()); |
| 173 | + auto debug_syms = dp.get_symbols(); |
| 174 | + symbols.insert(symbols.end(), debug_syms.begin(), debug_syms.end()); |
| 175 | + } |
| 176 | + } |
| 177 | + } |
| 178 | + |
130 | 179 | return symbols; |
131 | 180 | } |
132 | 181 |
|
|
0 commit comments