| ... | ... | @@ -15,9 +15,12 @@ const MachO = @import("../MachO.zig"); |
| 15 | 15 | const satMul = MachO.satMul; |
| 16 | 16 | const alloc_num = MachO.alloc_num; |
| 17 | 17 | const alloc_den = MachO.alloc_den; |
| 18 | const makeStaticString = MachO.makeStaticString; |
| 18 | 19 | |
| 19 | 20 | usingnamespace @import("commands.zig"); |
| 20 | 21 | |
| 22 | const page_size: u16 = 0x1000; |
| 23 | |
| 21 | 24 | base: *MachO, |
| 22 | 25 | file: fs.File, |
| 23 | 26 | |
| ... | ... | @@ -44,12 +47,25 @@ uuid_cmd_index: ?u16 = null, |
| 44 | 47 | /// Index into __TEXT,__text section. |
| 45 | 48 | text_section_index: ?u16 = null, |
| 46 | 49 | |
| 47 | | linkedit_off: u16 = 0x1000, |
| 48 | | linkedit_size: u16 = 0x1000, |
| 50 | linkedit_off: u16 = page_size, |
| 51 | linkedit_size: u16 = page_size, |
| 52 | |
| 53 | debug_info_section_index: ?u16 = null, |
| 54 | debug_abbrev_section_index: ?u16 = null, |
| 55 | debug_str_section_index: ?u16 = null, |
| 56 | debug_aranges_section_index: ?u16 = null, |
| 57 | debug_line_section_index: ?u16 = null, |
| 58 | |
| 59 | debug_abbrev_table_offset: ?u64 = null, |
| 49 | 60 | |
| 50 | 61 | header_dirty: bool = false, |
| 51 | 62 | load_commands_dirty: bool = false, |
| 52 | 63 | string_table_dirty: bool = false, |
| 64 | debug_string_table_dirty: bool = false, |
| 65 | debug_abbrev_section_dirty: bool = false, |
| 66 | debug_aranges_section_dirty: bool = false, |
| 67 | debug_info_header_dirty: bool = false, |
| 68 | debug_line_header_dirty: bool = false, |
| 53 | 69 | |
| 54 | 70 | /// You must call this function *after* `MachO.populateMissingMetadata()` |
| 55 | 71 | /// has been called to get a viable debug symbols output. |
| ... | ... | @@ -98,7 +114,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void |
| 98 | 114 | .strsize = base_cmd.strsize, |
| 99 | 115 | }, |
| 100 | 116 | }); |
| 101 | | try self.writeLocalSymbol(0); |
| 102 | 117 | self.header_dirty = true; |
| 103 | 118 | self.load_commands_dirty = true; |
| 104 | 119 | self.string_table_dirty = true; |
| ... | ... | @@ -139,6 +154,176 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void |
| 139 | 154 | self.header_dirty = true; |
| 140 | 155 | self.load_commands_dirty = true; |
| 141 | 156 | } |
| 157 | if (self.dwarf_segment_cmd_index == null) { |
| 158 | self.dwarf_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 159 | |
| 160 | const linkedit = self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| 161 | const ideal_size: u16 = 200 + 128 + 160 + 250; |
| 162 | const needed_size = mem.alignForwardGeneric(u64, satMul(ideal_size, alloc_num) / alloc_den, page_size); |
| 163 | const off = linkedit.inner.fileoff + linkedit.inner.filesize; |
| 164 | const vmaddr = linkedit.inner.vmaddr + linkedit.inner.vmsize; |
| 165 | |
| 166 | log.debug("found dSym __DWARF segment free space 0x{x} to 0x{x}", .{ off, off + needed_size }); |
| 167 | |
| 168 | try self.load_commands.append(allocator, .{ |
| 169 | .Segment = SegmentCommand.empty(.{ |
| 170 | .cmd = macho.LC_SEGMENT_64, |
| 171 | .cmdsize = @sizeOf(macho.segment_command_64), |
| 172 | .segname = makeStaticString("__DWARF"), |
| 173 | .vmaddr = vmaddr, |
| 174 | .vmsize = needed_size, |
| 175 | .fileoff = off, |
| 176 | .filesize = needed_size, |
| 177 | .maxprot = 0, |
| 178 | .initprot = 0, |
| 179 | .nsects = 0, |
| 180 | .flags = 0, |
| 181 | }), |
| 182 | }); |
| 183 | self.header_dirty = true; |
| 184 | self.load_commands_dirty = true; |
| 185 | } |
| 186 | if (self.debug_str_section_index == null) { |
| 187 | const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment; |
| 188 | self.debug_str_section_index = @intCast(u16, dwarf_segment.sections.items.len); |
| 189 | assert(self.base.debug_string_table.items.len == 0); |
| 190 | |
| 191 | const file_size_hint = 200; |
| 192 | const p_align = 1; |
| 193 | const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null); |
| 194 | |
| 195 | log.debug("found dSym __debug_strtab free space 0x{x} to 0x{x}", .{ off, off + file_size_hint }); |
| 196 | |
| 197 | try dwarf_segment.addSection(allocator, .{ |
| 198 | .sectname = makeStaticString("__debug_str"), |
| 199 | .segname = makeStaticString("__DWARF"), |
| 200 | .addr = dwarf_segment.inner.vmaddr + off, |
| 201 | .size = @intCast(u32, self.base.debug_string_table.items.len), |
| 202 | .offset = @intCast(u32, off), |
| 203 | .@"align" = 1, |
| 204 | .reloff = 0, |
| 205 | .nreloc = 0, |
| 206 | .flags = macho.S_REGULAR, |
| 207 | .reserved1 = 0, |
| 208 | .reserved2 = 0, |
| 209 | .reserved3 = 0, |
| 210 | }); |
| 211 | self.header_dirty = true; |
| 212 | self.load_commands_dirty = true; |
| 213 | self.debug_string_table_dirty = true; |
| 214 | } |
| 215 | if (self.debug_info_section_index == null) { |
| 216 | const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment; |
| 217 | self.debug_info_section_index = @intCast(u16, dwarf_segment.sections.items.len); |
| 218 | |
| 219 | const file_size_hint = 200; |
| 220 | const p_align = 1; |
| 221 | const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null); |
| 222 | |
| 223 | log.debug("found dSym __debug_info free space 0x{x} to 0x{x}", .{ off, off + file_size_hint }); |
| 224 | |
| 225 | try dwarf_segment.addSection(allocator, .{ |
| 226 | .sectname = makeStaticString("__debug_info"), |
| 227 | .segname = makeStaticString("__DWARF"), |
| 228 | .addr = dwarf_segment.inner.vmaddr + off, |
| 229 | .size = file_size_hint, |
| 230 | .offset = @intCast(u32, off), |
| 231 | .@"align" = p_align, |
| 232 | .reloff = 0, |
| 233 | .nreloc = 0, |
| 234 | .flags = macho.S_REGULAR, |
| 235 | .reserved1 = 0, |
| 236 | .reserved2 = 0, |
| 237 | .reserved3 = 0, |
| 238 | }); |
| 239 | self.header_dirty = true; |
| 240 | self.load_commands_dirty = true; |
| 241 | self.debug_info_header_dirty = true; |
| 242 | } |
| 243 | if (self.debug_abbrev_section_index == null) { |
| 244 | const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment; |
| 245 | self.debug_abbrev_section_index = @intCast(u16, dwarf_segment.sections.items.len); |
| 246 | |
| 247 | const file_size_hint = 128; |
| 248 | const p_align = 1; |
| 249 | const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null); |
| 250 | |
| 251 | log.debug("found dSym __debug_abbrev free space 0x{x} to 0x{x}", .{ off, off + file_size_hint }); |
| 252 | |
| 253 | try dwarf_segment.addSection(allocator, .{ |
| 254 | .sectname = makeStaticString("__debug_abbrev"), |
| 255 | .segname = makeStaticString("__DWARF"), |
| 256 | .addr = dwarf_segment.inner.vmaddr + off, |
| 257 | .size = file_size_hint, |
| 258 | .offset = @intCast(u32, off), |
| 259 | .@"align" = p_align, |
| 260 | .reloff = 0, |
| 261 | .nreloc = 0, |
| 262 | .flags = macho.S_REGULAR, |
| 263 | .reserved1 = 0, |
| 264 | .reserved2 = 0, |
| 265 | .reserved3 = 0, |
| 266 | }); |
| 267 | self.header_dirty = true; |
| 268 | self.load_commands_dirty = true; |
| 269 | self.debug_abbrev_section_dirty = true; |
| 270 | } |
| 271 | if (self.debug_aranges_section_index == null) { |
| 272 | const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment; |
| 273 | self.debug_aranges_section_index = @intCast(u16, dwarf_segment.sections.items.len); |
| 274 | |
| 275 | const file_size_hint = 160; |
| 276 | const p_align = 16; |
| 277 | const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null); |
| 278 | |
| 279 | log.debug("found dSym __debug_aranges free space 0x{x} to 0x{x}", .{ off, off + file_size_hint }); |
| 280 | |
| 281 | try dwarf_segment.addSection(allocator, .{ |
| 282 | .sectname = makeStaticString("__debug_aranges"), |
| 283 | .segname = makeStaticString("__DWARF"), |
| 284 | .addr = dwarf_segment.inner.vmaddr + off, |
| 285 | .size = file_size_hint, |
| 286 | .offset = @intCast(u32, off), |
| 287 | .@"align" = p_align, |
| 288 | .reloff = 0, |
| 289 | .nreloc = 0, |
| 290 | .flags = macho.S_REGULAR, |
| 291 | .reserved1 = 0, |
| 292 | .reserved2 = 0, |
| 293 | .reserved3 = 0, |
| 294 | }); |
| 295 | self.header_dirty = true; |
| 296 | self.load_commands_dirty = true; |
| 297 | self.debug_aranges_section_dirty = true; |
| 298 | } |
| 299 | if (self.debug_line_section_index == null) { |
| 300 | const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment; |
| 301 | self.debug_line_section_index = @intCast(u16, dwarf_segment.sections.items.len); |
| 302 | |
| 303 | const file_size_hint = 250; |
| 304 | const p_align = 1; |
| 305 | const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null); |
| 306 | |
| 307 | log.debug("found dSym __debug_line free space 0x{x} to 0x{x}", .{ off, off + file_size_hint }); |
| 308 | |
| 309 | try dwarf_segment.addSection(allocator, .{ |
| 310 | .sectname = makeStaticString("__debug_line"), |
| 311 | .segname = makeStaticString("__DWARF"), |
| 312 | .addr = dwarf_segment.inner.vmaddr + off, |
| 313 | .size = file_size_hint, |
| 314 | .offset = @intCast(u32, off), |
| 315 | .@"align" = p_align, |
| 316 | .reloff = 0, |
| 317 | .nreloc = 0, |
| 318 | .flags = macho.S_REGULAR, |
| 319 | .reserved1 = 0, |
| 320 | .reserved2 = 0, |
| 321 | .reserved3 = 0, |
| 322 | }); |
| 323 | self.header_dirty = true; |
| 324 | self.load_commands_dirty = true; |
| 325 | self.debug_line_header_dirty = true; |
| 326 | } |
| 142 | 327 | } |
| 143 | 328 | |
| 144 | 329 | pub fn flush(self: *DebugSymbols, allocator: *Allocator) !void { |