├── .gitignore ├── LICENSE ├── README.md ├── elf_parser.cpp ├── elf_parser.hpp └── examples ├── Makefile ├── relocations.cc ├── sections.cc ├── segments.cc └── symbols.cc /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | 35 | examples/sections 36 | examples/segments 37 | examples/symbols 38 | examples/relocations 39 | examples/tests/test1 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 finixbit 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # elf-parser 2 | Lightweight elf binary parser with no external dependencies - Sections, Symbols, Relocations, Segments 3 | 4 | # Required libraries 5 | No dependencies 6 | 7 | # Usage 8 | 9 | ## Sections (readelf -S executable) 10 | parse sections header table from elf binary and return vector of section_t below 11 | 12 | ```cpp 13 | typedef struct { 14 | int section_index = 0; 15 | std::intptr_t section_offset, section_addr; 16 | std::string section_name; 17 | std::string section_type; 18 | int section_size, section_ent_size, section_addr_align; 19 | } section_t; 20 | ``` 21 | 22 | get elf sections using elf-parser 23 | 24 | ```cpp 25 | #include 26 | elf_parser::Elf_parser elf_parser(executable_path); 27 | std::vector secs = elf_parser.get_sections(); 28 | ``` 29 | see [example](examples/sections.cc) 30 | 31 | ## Segments (readelf -l executable) 32 | parse program header table from elf binary and return vector of segment_t below 33 | 34 | ```cpp 35 | typedef struct { 36 | std::string segment_type, segment_flags; 37 | long segment_offset, segment_virtaddr, segment_physaddr, segment_filesize, segment_memsize; 38 | int segment_align; 39 | } segment_t; 40 | ``` 41 | 42 | get elf segments using elf-parser 43 | 44 | ```cpp 45 | #include 46 | elf_parser::Elf_parser elf_parser(executable_path); 47 | std::vector segs = elf_parser.get_segments(); 48 | ``` 49 | see [example](examples/segments.cc) 50 | 51 | ## Symbols (readelf -s executable) 52 | parse symbols table from elf binary and return vector of symbol_t below 53 | 54 | ```cpp 55 | typedef struct { 56 | std::string symbol_index; 57 | std::intptr_t symbol_value; 58 | int symbol_num = 0, symbol_size = 0; 59 | std::string symbol_type, symbol_bind, symbol_visibility, symbol_name, symbol_section; 60 | } symbol_t; 61 | ``` 62 | 63 | get elf symbols using elf-parser 64 | 65 | ```cpp 66 | #include 67 | elf_parser::Elf_parser elf_parser(executable_path); 68 | std::vector syms = elf_parser.get_symbols(); 69 | ``` 70 | see [example](examples/symbols.cc) 71 | 72 | ## Relocations (readelf -r executable) 73 | parse relocations with plt address from elf binary and return vector of relocation_t below 74 | 75 | ```cpp 76 | typedef struct { 77 | std::intptr_t relocation_offset, relocation_info, relocation_symbol_value; 78 | std::string relocation_type, relocation_symbol_name, relocation_section_name; 79 | std::intptr_t relocation_plt_address; 80 | } relocation_t; 81 | ``` 82 | 83 | get elf relocations using elf-parser 84 | 85 | ```cpp 86 | #include 87 | elf_parser::Elf_parser elf_parser(executable_path); 88 | std::vector relocs = elf_parser.get_relocations(); 89 | ``` 90 | see [example](examples/relocations.cc) 91 | 92 | 93 | # Supported Architecture 94 | amd64 95 | 96 | # Projects using elf-parser 97 | [finixbit / ltrace - Library call tracer](http://github.com/finixbit/ltrace) 98 | 99 | [finixbit / ftrace - Function call tracer](http://github.com/finixbit/ftrace) 100 | 101 | -------------------------------------------------------------------------------- /elf_parser.cpp: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2018 finixbit 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include "elf_parser.hpp" 24 | using namespace elf_parser; 25 | 26 | std::vector Elf_parser::get_sections() { 27 | Elf64_Ehdr *ehdr = (Elf64_Ehdr*)m_mmap_program; 28 | Elf64_Shdr *shdr = (Elf64_Shdr*)(m_mmap_program + ehdr->e_shoff); 29 | int shnum = ehdr->e_shnum; 30 | 31 | Elf64_Shdr *sh_strtab = &shdr[ehdr->e_shstrndx]; 32 | const char *const sh_strtab_p = (char*)m_mmap_program + sh_strtab->sh_offset; 33 | 34 | std::vector sections; 35 | for (int i = 0; i < shnum; ++i) { 36 | section_t section; 37 | section.section_index= i; 38 | section.section_name = std::string(sh_strtab_p + shdr[i].sh_name); 39 | section.section_type = get_section_type(shdr[i].sh_type); 40 | section.section_addr = shdr[i].sh_addr; 41 | section.section_offset = shdr[i].sh_offset; 42 | section.section_size = shdr[i].sh_size; 43 | section.section_ent_size = shdr[i].sh_entsize; 44 | section.section_addr_align = shdr[i].sh_addralign; 45 | 46 | sections.push_back(section); 47 | } 48 | return sections; 49 | } 50 | 51 | std::vector Elf_parser::get_segments() { 52 | Elf64_Ehdr *ehdr = (Elf64_Ehdr*)m_mmap_program; 53 | Elf64_Phdr *phdr = (Elf64_Phdr*)(m_mmap_program + ehdr->e_phoff); 54 | int phnum = ehdr->e_phnum; 55 | 56 | Elf64_Shdr *shdr = (Elf64_Shdr*)(m_mmap_program + ehdr->e_shoff); 57 | Elf64_Shdr *sh_strtab = &shdr[ehdr->e_shstrndx]; 58 | const char *const sh_strtab_p = (char*)m_mmap_program + sh_strtab->sh_offset; 59 | 60 | std::vector segments; 61 | for (int i = 0; i < phnum; ++i) { 62 | segment_t segment; 63 | segment.segment_type = get_segment_type(phdr[i].p_type); 64 | segment.segment_offset = phdr[i].p_offset; 65 | segment.segment_virtaddr = phdr[i].p_vaddr; 66 | segment.segment_physaddr = phdr[i].p_paddr; 67 | segment.segment_filesize = phdr[i].p_filesz; 68 | segment.segment_memsize = phdr[i].p_memsz; 69 | segment.segment_flags = get_segment_flags(phdr[i].p_flags); 70 | segment.segment_align = phdr[i].p_align; 71 | 72 | segments.push_back(segment); 73 | } 74 | return segments; 75 | } 76 | 77 | std::vector Elf_parser::get_symbols() { 78 | std::vector secs = get_sections(); 79 | 80 | // get headers for offsets 81 | Elf64_Ehdr *ehdr = (Elf64_Ehdr*)m_mmap_program; 82 | Elf64_Shdr *shdr = (Elf64_Shdr*)(m_mmap_program + ehdr->e_shoff); 83 | 84 | // get strtab 85 | 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 | // get dynstr 94 | 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; 99 | } 100 | } 101 | 102 | std::vector symbols; 103 | for(auto &sec: secs) { 104 | if((sec.section_type != "SHT_SYMTAB") && (sec.section_type != "SHT_DYNSYM")) 105 | continue; 106 | 107 | auto total_syms = sec.section_size / sizeof(Elf64_Sym); 108 | auto syms_data = (Elf64_Sym*)(m_mmap_program + sec.section_offset); 109 | 110 | for (int i = 0; i < total_syms; ++i) { 111 | symbol_t symbol; 112 | symbol.symbol_num = i; 113 | symbol.symbol_value = syms_data[i].st_value; 114 | symbol.symbol_size = syms_data[i].st_size; 115 | symbol.symbol_type = get_symbol_type(syms_data[i].st_info); 116 | symbol.symbol_bind = get_symbol_bind(syms_data[i].st_info); 117 | symbol.symbol_visibility= get_symbol_visibility(syms_data[i].st_other); 118 | symbol.symbol_index = get_symbol_index(syms_data[i].st_shndx); 119 | symbol.symbol_section = sec.section_name; 120 | 121 | if(sec.section_type == "SHT_SYMTAB") 122 | symbol.symbol_name = std::string(sh_strtab_p + syms_data[i].st_name); 123 | 124 | if(sec.section_type == "SHT_DYNSYM") 125 | symbol.symbol_name = std::string(sh_dynstr_p + syms_data[i].st_name); 126 | 127 | symbols.push_back(symbol); 128 | } 129 | } 130 | return symbols; 131 | } 132 | 133 | std::vector Elf_parser::get_relocations() { 134 | auto secs = get_sections(); 135 | auto syms = get_symbols(); 136 | 137 | int plt_entry_size = 0; 138 | long plt_vma_address = 0; 139 | 140 | for (auto &sec : secs) { 141 | if(sec.section_name == ".plt") { 142 | plt_entry_size = sec.section_ent_size; 143 | plt_vma_address = sec.section_addr; 144 | break; 145 | } 146 | } 147 | 148 | std::vector relocations; 149 | for (auto &sec : secs) { 150 | 151 | if(sec.section_type != "SHT_RELA") 152 | continue; 153 | 154 | auto total_relas = sec.section_size / sizeof(Elf64_Rela); 155 | auto relas_data = (Elf64_Rela*)(m_mmap_program + sec.section_offset); 156 | 157 | for (int i = 0; i < total_relas; ++i) { 158 | relocation_t rel; 159 | rel.relocation_offset = static_cast(relas_data[i].r_offset); 160 | rel.relocation_info = static_cast(relas_data[i].r_info); 161 | rel.relocation_type = \ 162 | get_relocation_type(relas_data[i].r_info); 163 | 164 | rel.relocation_symbol_value = \ 165 | get_rel_symbol_value(relas_data[i].r_info, syms); 166 | 167 | rel.relocation_symbol_name = \ 168 | get_rel_symbol_name(relas_data[i].r_info, syms); 169 | 170 | rel.relocation_plt_address = plt_vma_address + (i + 1) * plt_entry_size; 171 | rel.relocation_section_name = sec.section_name; 172 | 173 | relocations.push_back(rel); 174 | } 175 | } 176 | return relocations; 177 | } 178 | 179 | uint8_t *Elf_parser::get_memory_map() { 180 | return m_mmap_program; 181 | } 182 | 183 | void Elf_parser::load_memory_map() { 184 | int fd, i; 185 | struct stat st; 186 | 187 | if ((fd = open(m_program_path.c_str(), O_RDONLY)) < 0) { 188 | printf("Err: open\n"); 189 | exit(-1); 190 | } 191 | if (fstat(fd, &st) < 0) { 192 | printf("Err: fstat\n"); 193 | exit(-1); 194 | } 195 | m_mmap_program = static_cast(mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)); 196 | if (m_mmap_program == MAP_FAILED) { 197 | printf("Err: mmap\n"); 198 | exit(-1); 199 | } 200 | 201 | auto header = (Elf64_Ehdr*)m_mmap_program; 202 | if (header->e_ident[EI_CLASS] != ELFCLASS64) { 203 | printf("Only 64-bit files supported\n"); 204 | exit(1); 205 | } 206 | } 207 | 208 | std::string Elf_parser::get_section_type(int tt) { 209 | if(tt < 0) 210 | return "UNKNOWN"; 211 | 212 | switch(tt) { 213 | case 0: return "SHT_NULL"; /* Section header table entry unused */ 214 | case 1: return "SHT_PROGBITS"; /* Program data */ 215 | case 2: return "SHT_SYMTAB"; /* Symbol table */ 216 | case 3: return "SHT_STRTAB"; /* String table */ 217 | case 4: return "SHT_RELA"; /* Relocation entries with addends */ 218 | case 5: return "SHT_HASH"; /* Symbol hash table */ 219 | case 6: return "SHT_DYNAMIC"; /* Dynamic linking information */ 220 | case 7: return "SHT_NOTE"; /* Notes */ 221 | case 8: return "SHT_NOBITS"; /* Program space with no data (bss) */ 222 | case 9: return "SHT_REL"; /* Relocation entries, no addends */ 223 | case 11: return "SHT_DYNSYM"; /* Dynamic linker symbol table */ 224 | default: return "UNKNOWN"; 225 | } 226 | return "UNKNOWN"; 227 | } 228 | 229 | std::string Elf_parser::get_segment_type(uint32_t &seg_type) { 230 | switch(seg_type) { 231 | case PT_NULL: return "NULL"; /* Program header table entry unused */ 232 | case PT_LOAD: return "LOAD"; /* Loadable program segment */ 233 | case PT_DYNAMIC: return "DYNAMIC"; /* Dynamic linking information */ 234 | case PT_INTERP: return "INTERP"; /* Program interpreter */ 235 | case PT_NOTE: return "NOTE"; /* Auxiliary information */ 236 | case PT_SHLIB: return "SHLIB"; /* Reserved */ 237 | case PT_PHDR: return "PHDR"; /* Entry for header table itself */ 238 | case PT_TLS: return "TLS"; /* Thread-local storage segment */ 239 | case PT_NUM: return "NUM"; /* Number of defined types */ 240 | case PT_LOOS: return "LOOS"; /* Start of OS-specific */ 241 | case PT_GNU_EH_FRAME: return "GNU_EH_FRAME"; /* GCC .eh_frame_hdr segment */ 242 | case PT_GNU_STACK: return "GNU_STACK"; /* Indicates stack executability */ 243 | case PT_GNU_RELRO: return "GNU_RELRO"; /* Read-only after relocation */ 244 | //case PT_LOSUNW: return "LOSUNW"; 245 | case PT_SUNWBSS: return "SUNWBSS"; /* Sun Specific segment */ 246 | case PT_SUNWSTACK: return "SUNWSTACK"; /* Stack segment */ 247 | //case PT_HISUNW: return "HISUNW"; 248 | case PT_HIOS: return "HIOS"; /* End of OS-specific */ 249 | case PT_LOPROC: return "LOPROC"; /* Start of processor-specific */ 250 | case PT_HIPROC: return "HIPROC"; /* End of processor-specific */ 251 | default: return "UNKNOWN"; 252 | } 253 | } 254 | 255 | std::string Elf_parser::get_segment_flags(uint32_t &seg_flags) { 256 | std::string flags; 257 | 258 | if(seg_flags & PF_R) 259 | flags.append("R"); 260 | 261 | if(seg_flags & PF_W) 262 | flags.append("W"); 263 | 264 | if(seg_flags & PF_X) 265 | flags.append("E"); 266 | 267 | return flags; 268 | } 269 | 270 | std::string Elf_parser::get_symbol_type(uint8_t &sym_type) { 271 | switch(ELF32_ST_TYPE(sym_type)) { 272 | case 0: return "NOTYPE"; 273 | case 1: return "OBJECT"; 274 | case 2: return "FUNC"; 275 | case 3: return "SECTION"; 276 | case 4: return "FILE"; 277 | case 6: return "TLS"; 278 | case 7: return "NUM"; 279 | case 10: return "LOOS"; 280 | case 12: return "HIOS"; 281 | default: return "UNKNOWN"; 282 | } 283 | } 284 | 285 | std::string Elf_parser::get_symbol_bind(uint8_t &sym_bind) { 286 | switch(ELF32_ST_BIND(sym_bind)) { 287 | case 0: return "LOCAL"; 288 | case 1: return "GLOBAL"; 289 | case 2: return "WEAK"; 290 | case 3: return "NUM"; 291 | case 10: return "UNIQUE"; 292 | case 12: return "HIOS"; 293 | case 13: return "LOPROC"; 294 | default: return "UNKNOWN"; 295 | } 296 | } 297 | 298 | std::string Elf_parser::get_symbol_visibility(uint8_t &sym_vis) { 299 | switch(ELF32_ST_VISIBILITY(sym_vis)) { 300 | case 0: return "DEFAULT"; 301 | case 1: return "INTERNAL"; 302 | case 2: return "HIDDEN"; 303 | case 3: return "PROTECTED"; 304 | default: return "UNKNOWN"; 305 | } 306 | } 307 | 308 | std::string Elf_parser::get_symbol_index(uint16_t &sym_idx) { 309 | switch(sym_idx) { 310 | case SHN_ABS: return "ABS"; 311 | case SHN_COMMON: return "COM"; 312 | case SHN_UNDEF: return "UND"; 313 | case SHN_XINDEX: return "COM"; 314 | default: return std::to_string(sym_idx); 315 | } 316 | } 317 | 318 | std::string Elf_parser::get_relocation_type(uint64_t &rela_type) { 319 | switch(ELF64_R_TYPE(rela_type)) { 320 | case 1: return "R_X86_64_32"; 321 | case 2: return "R_X86_64_PC32"; 322 | case 5: return "R_X86_64_COPY"; 323 | case 6: return "R_X86_64_GLOB_DAT"; 324 | case 7: return "R_X86_64_JUMP_SLOT"; 325 | default: return "OTHERS"; 326 | } 327 | } 328 | 329 | std::intptr_t Elf_parser::get_rel_symbol_value( 330 | uint64_t &sym_idx, std::vector &syms) { 331 | 332 | std::intptr_t sym_val = 0; 333 | for(auto &sym: syms) { 334 | if(sym.symbol_num == ELF64_R_SYM(sym_idx)) { 335 | sym_val = sym.symbol_value; 336 | break; 337 | } 338 | } 339 | return sym_val; 340 | } 341 | 342 | std::string Elf_parser::get_rel_symbol_name( 343 | uint64_t &sym_idx, std::vector &syms) { 344 | 345 | std::string sym_name; 346 | for(auto &sym: syms) { 347 | if(sym.symbol_num == ELF64_R_SYM(sym_idx)) { 348 | sym_name = sym.symbol_name; 349 | break; 350 | } 351 | } 352 | return sym_name; 353 | } 354 | -------------------------------------------------------------------------------- /elf_parser.hpp: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2018 finixbit 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #ifndef H_ELF_PARSER 24 | #define H_ELF_PARSER 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include /* O_RDONLY */ 31 | #include /* For the size of the file. , fstat */ 32 | #include /* mmap, MAP_PRIVATE */ 33 | #include 34 | #include // Elf64_Shdr 35 | #include 36 | 37 | namespace elf_parser { 38 | 39 | typedef struct { 40 | int section_index = 0; 41 | std::intptr_t section_offset, section_addr; 42 | std::string section_name; 43 | std::string section_type; 44 | int section_size, section_ent_size, section_addr_align; 45 | } section_t; 46 | 47 | typedef struct { 48 | std::string segment_type, segment_flags; 49 | long segment_offset, segment_virtaddr, segment_physaddr, segment_filesize, segment_memsize; 50 | int segment_align; 51 | } segment_t; 52 | 53 | typedef struct { 54 | std::string symbol_index; 55 | std::intptr_t symbol_value; 56 | int symbol_num = 0, symbol_size = 0; 57 | std::string symbol_type, symbol_bind, symbol_visibility, symbol_name, symbol_section; 58 | } symbol_t; 59 | 60 | typedef struct { 61 | std::intptr_t relocation_offset, relocation_info, relocation_symbol_value; 62 | std::string relocation_type, relocation_symbol_name, relocation_section_name; 63 | std::intptr_t relocation_plt_address; 64 | } relocation_t; 65 | 66 | 67 | class Elf_parser { 68 | public: 69 | Elf_parser (std::string &program_path): m_program_path{program_path} { 70 | load_memory_map(); 71 | } 72 | std::vector get_sections(); 73 | std::vector get_segments(); 74 | std::vector get_symbols(); 75 | std::vector get_relocations(); 76 | uint8_t *get_memory_map(); 77 | 78 | private: 79 | void load_memory_map(); 80 | 81 | std::string get_section_type(int tt); 82 | 83 | std::string get_segment_type(uint32_t &seg_type); 84 | std::string get_segment_flags(uint32_t &seg_flags); 85 | 86 | std::string get_symbol_type(uint8_t &sym_type); 87 | std::string get_symbol_bind(uint8_t &sym_bind); 88 | std::string get_symbol_visibility(uint8_t &sym_vis); 89 | std::string get_symbol_index(uint16_t &sym_idx); 90 | 91 | std::string get_relocation_type(uint64_t &rela_type); 92 | std::intptr_t get_rel_symbol_value(uint64_t &sym_idx, std::vector &syms); 93 | std::string get_rel_symbol_name( 94 | uint64_t &sym_idx, std::vector &syms); 95 | 96 | std::string m_program_path; 97 | uint8_t *m_mmap_program; 98 | }; 99 | 100 | } 101 | #endif -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | all: sections symbols segments relocations 4 | 5 | sections: sections.cc 6 | g++ -o sections sections.cc ../elf_parser.cpp -std=gnu++11 7 | 8 | symbols: symbols.cc 9 | g++ -o symbols symbols.cc ../elf_parser.cpp -std=gnu++11 10 | 11 | segments: segments.cc 12 | g++ -o segments segments.cc ../elf_parser.cpp -std=gnu++11 13 | 14 | relocations: relocations.cc 15 | g++ -o relocations relocations.cc ../elf_parser.cpp -std=gnu++11 16 | 17 | clean: 18 | rm -f sections symbols segments relocations -------------------------------------------------------------------------------- /examples/relocations.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include // PRIx64 3 | #include "../elf_parser.hpp" 4 | 5 | void print_relocations(std::vector &relocations); 6 | 7 | int main(int argc, char* argv[]) { 8 | char usage_banner[] = "usage: ./sections []\n"; 9 | if(argc < 2) { 10 | std::cerr << usage_banner; 11 | return -1; 12 | } 13 | 14 | std::string program((std::string)argv[1]); 15 | elf_parser::Elf_parser elf_parser(program); 16 | 17 | std::vector relocs = elf_parser.get_relocations(); 18 | print_relocations(relocs); 19 | return 0; 20 | } 21 | 22 | void print_relocations(std::vector &relocations) { 23 | printf(" [*] %-16s %-16s %-16s %-16s %s\n", "Offset", "Info", "Type", "Sym. Value", "Sym. Name (section)"); 24 | printf(" [*] %-16s\n", "Calculated PLT Address"); 25 | for (auto &rel : relocations) { 26 | printf("%016" PRIx64 " %016" PRIx64 " %-16s %016" PRIx64 " %-16s (%s)\n", 27 | rel.relocation_offset, 28 | rel.relocation_info, 29 | rel.relocation_type.c_str(), 30 | rel.relocation_symbol_value, 31 | rel.relocation_symbol_name.c_str(), 32 | rel.relocation_section_name.c_str()); 33 | printf("%016" PRIx64 "\n", rel.relocation_plt_address); 34 | } 35 | } -------------------------------------------------------------------------------- /examples/sections.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include // PRIx64 3 | #include "../elf_parser.hpp" 4 | 5 | void print_sections(std::vector §ions); 6 | 7 | int main(int argc, char* argv[]) { 8 | char usage_banner[] = "usage: ./sections []\n"; 9 | if(argc < 2) { 10 | std::cerr << usage_banner; 11 | return -1; 12 | } 13 | 14 | std::string program((std::string)argv[1]); 15 | elf_parser::Elf_parser elf_parser(program); 16 | 17 | std::vector secs = elf_parser.get_sections(); 18 | print_sections(secs); 19 | return 0; 20 | } 21 | 22 | void print_sections(std::vector §ions) { 23 | printf(" [Nr] %-16s %-16s %-16s %s\n", "Name", "Type", "Address", "Offset"); 24 | printf(" %-16s %-16s %5s\n", 25 | "Size", "EntSize", "Align"); 26 | 27 | for (auto §ion : sections) { 28 | printf(" [%2d] %-16s %-16s %016" PRIx64 " %08" PRIx64 "\n", 29 | section.section_index, 30 | section.section_name.c_str(), 31 | section.section_type.c_str(), 32 | section.section_addr, 33 | section.section_offset); 34 | 35 | printf(" %016zx %016" PRIx64 " %5" PRIu64 "\n", 36 | section.section_size, 37 | section.section_ent_size, 38 | section.section_addr_align); 39 | } 40 | } -------------------------------------------------------------------------------- /examples/segments.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include // PRIx64 3 | #include "../elf_parser.hpp" 4 | 5 | void print_segments(std::vector &segments); 6 | 7 | int main(int argc, char* argv[]) { 8 | char usage_banner[] = "usage: ./sections []\n"; 9 | if(argc < 2) { 10 | std::cerr << usage_banner; 11 | return -1; 12 | } 13 | 14 | std::string program((std::string)argv[1]); 15 | elf_parser::Elf_parser elf_parser(program); 16 | 17 | std::vector segs = elf_parser.get_segments(); 18 | print_segments(segs); 19 | return 0; 20 | } 21 | 22 | void print_segments(std::vector &segments) { 23 | printf(" %-16s %-16s %-16s %s\n", "Type", "Offset", "VirtAddr", "PhysAddr"); 24 | printf(" %-16s %-16s %-16s %6s %5s\n", " ", "FileSiz", "MemSiz", "Flags", "Align"); 25 | 26 | for (auto &segment : segments) { 27 | printf(" %-16s 0x%016" PRIx64 " 0x%016" PRIx64 " 0x%016" PRIx64 "\n", 28 | segment.segment_type.c_str(), 29 | segment.segment_offset, 30 | segment.segment_virtaddr, 31 | segment.segment_physaddr); 32 | 33 | printf(" %-16s 0x%016" PRIx64 " 0x%016" PRIx64 " %-5s %-5" PRIx64 "\n", "", 34 | segment.segment_filesize, 35 | segment.segment_memsize, 36 | segment.segment_flags.c_str(), 37 | segment.segment_align); 38 | } 39 | } -------------------------------------------------------------------------------- /examples/symbols.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include // PRIx64 3 | #include "../elf_parser.hpp" 4 | 5 | void print_symbols(std::vector &symbols); 6 | 7 | int main(int argc, char* argv[]) { 8 | char usage_banner[] = "usage: ./sections []\n"; 9 | if(argc < 2) { 10 | std::cerr << usage_banner; 11 | return -1; 12 | } 13 | 14 | std::string program((std::string)argv[1]); 15 | elf_parser::Elf_parser elf_parser(program); 16 | 17 | std::vector syms = elf_parser.get_symbols(); 18 | print_symbols(syms); 19 | return 0; 20 | } 21 | 22 | void print_symbols(std::vector &symbols) { 23 | printf("Num: Value Size Type Bind Vis Ndx Name\n"); 24 | for (auto &symbol : symbols) { 25 | printf("%-3d: %08" PRIx64 " %-4d %-8s %-7s %-9s %-3s %s(%s)\n", 26 | symbol.symbol_num, 27 | symbol.symbol_value, 28 | symbol.symbol_size, 29 | symbol.symbol_type.c_str(), 30 | symbol.symbol_bind.c_str(), 31 | symbol.symbol_visibility.c_str(), 32 | symbol.symbol_index.c_str(), 33 | symbol.symbol_name.c_str(), 34 | symbol.symbol_section.c_str()); 35 | } 36 | } --------------------------------------------------------------------------------