draugr~ single ELF file analysis tool |
| git clone https://github.com/djnnvx/draugr.git |
| log | files | refs | archive | README |
json.odin (4943B)
1 package elf 2 3 import "core:encoding/json" 4 import "core:fmt" 5 6 Json_Symbol :: struct { 7 name : string, 8 value : u64, 9 size : u64, 10 bind : string, 11 type : string, 12 shndx : u16, 13 } 14 15 Json_Section :: struct { 16 index : int, 17 name : string, 18 type : string, 19 addr : u64, 20 offset : u64, 21 size : u64, 22 flags : u64, 23 } 24 25 Json_Segment :: struct { 26 type : string, 27 flags : string, 28 offset : u64, 29 vaddr : u64, 30 paddr : u64, 31 filesz : u64, 32 memsz : u64, 33 align : u64, 34 } 35 36 Json_Dyn :: struct { 37 tag : string, 38 value : u64, 39 name : string, 40 } 41 42 Json_Reloc :: struct { 43 offset : u64, 44 type : string, 45 addend : i64, 46 symbol : string, 47 source : string, 48 } 49 50 Json_Checksec :: struct { 51 relro : string, 52 nx : string, 53 pie : string, 54 canary : bool, 55 textrel : bool, 56 rwx_segment : bool, 57 rpath : string, 58 runpath : string, 59 stripped : bool, 60 fortified : int, 61 fortifiable : int, 62 partial : int, 63 } 64 65 Json_Dump :: struct { 66 class : int, 67 endian : string, 68 type : string, 69 machine : string, 70 entry : u64, 71 flags : u32, 72 pie : bool, 73 is_dynamic : bool, 74 interp_offset : u64, 75 soname : string, 76 rpath : string, 77 runpath : string, 78 needed : []string, 79 segments : []Json_Segment, 80 sections : []Json_Section, 81 dynamic_entries : []Json_Dyn, 82 symbols : []Json_Symbol, 83 dyn_symbols : []Json_Symbol, 84 relocations : []Json_Reloc, 85 got : map[string]u64, 86 checksec : Json_Checksec, 87 } 88 89 build_json_dump :: proc(info: ^ELF_Info, allocator := context.allocator) -> Json_Dump { 90 segments := make([]Json_Segment, len(info.program_hdrs), allocator) 91 for ph, i in info.program_hdrs { 92 segments[i] = Json_Segment{ 93 type = segment_type_str(ph.type), 94 flags = flags_to_str(ph.flags), 95 offset = ph.offset, 96 vaddr = ph.vaddr, 97 paddr = ph.paddr, 98 filesz = ph.filesz, 99 memsz = ph.memsz, 100 align = ph.align, 101 } 102 } 103 104 sections := make([]Json_Section, len(info.section_hdrs), allocator) 105 for shdr, i in info.section_hdrs { 106 sections[i] = Json_Section{ 107 index = i, 108 name = get_section_name(info, shdr), 109 type = section_type_str(shdr.type), 110 addr = shdr.addr, 111 offset = shdr.offset, 112 size = shdr.size, 113 flags = shdr.flags, 114 } 115 } 116 117 dyn := make([]Json_Dyn, len(info.dyn_entries), allocator) 118 for e, i in info.dyn_entries { 119 dyn[i] = Json_Dyn{tag = dyn_tag_str(e.tag), value = e.val, name = dyn_string(info, e)} 120 } 121 122 relocs := make([]Json_Reloc, len(info.relocs), allocator) 123 got := make(map[string]u64, allocator) 124 for r, i in info.relocs { 125 relocs[i] = Json_Reloc{ 126 offset = r.offset, 127 type = reloc_type_str(info.header.machine, r.type), 128 addend = r.addend, 129 symbol = r.sym_name, 130 source = r.source, 131 } 132 if is_jump_slot(info.header.machine, r.type) && r.sym_name != "" { 133 got[r.sym_name] = r.offset 134 } 135 } 136 137 c := checksec(info) 138 139 return Json_Dump{ 140 class = 64 if info.is_64bit else 32, 141 endian = "little" if info.header.data == ELF_DATA_LSB else "big", 142 type = type_to_str(info.header.type), 143 machine = machine_to_str(info.header.machine), 144 entry = info.header.entry, 145 flags = info.header.flags, 146 pie = info.is_pie, 147 is_dynamic = info.is_dynamic, 148 interp_offset = info.interp_offset, 149 soname = info.soname, 150 rpath = info.rpath, 151 runpath = info.runpath, 152 needed = info.needed[:], 153 segments = segments, 154 sections = sections, 155 dynamic_entries = dyn, 156 symbols = to_json_symbols(info.symbols[:], allocator), 157 dyn_symbols = to_json_symbols(info.dyn_symbols[:], allocator), 158 relocations = relocs, 159 got = got, 160 checksec = Json_Checksec{ 161 relro = relro_str(c.relro), 162 nx = nx_str(c.nx), 163 pie = pie_str(c.pie), 164 canary = c.canary, 165 textrel = c.textrel, 166 rwx_segment = c.rwx_segment, 167 rpath = c.rpath, 168 runpath = c.runpath, 169 stripped = c.stripped, 170 fortified = c.fortified, 171 fortifiable = c.fortifiable, 172 partial = c.partial, 173 }, 174 } 175 } 176 177 to_json_symbols :: proc(syms: []Symbol, allocator := context.allocator) -> []Json_Symbol { 178 out := make([]Json_Symbol, len(syms), allocator) 179 for sym, i in syms { 180 out[i] = Json_Symbol{ 181 name = sym.name, 182 value = sym.value, 183 size = sym.size, 184 bind = symbol_bind_str(sym.bind), 185 type = symbol_type_str(sym.type), 186 shndx = sym.shndx, 187 } 188 } 189 return out 190 } 191 192 print_json :: proc(info: ^ELF_Info) -> string { 193 defer free_all(context.temp_allocator) 194 195 dump := build_json_dump(info, context.temp_allocator) 196 data, err := json.marshal(dump, {pretty = true, use_spaces = true}, context.temp_allocator) 197 if err != nil { 198 return fmt.tprintf("json marshal failed: %v", err) 199 } 200 201 fmt.println(string(data)) 202 return "" 203 }