| ... | ... | @@ -255,6 +255,8 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void { |
| 255 | 255 | page.kind = .compressed; |
| 256 | 256 | } |
| 257 | 257 | |
| 258 | page.size = page.calcSize(); |
| 259 | |
| 258 | 260 | log.debug("{f}", .{page.fmt(info.*)}); |
| 259 | 261 | |
| 260 | 262 | try info.pages.append(gpa, page); |
| ... | ... | @@ -285,7 +287,9 @@ pub fn calcSize(info: UnwindInfo) usize { |
| 285 | 287 | total_size += @as(usize, @intCast(info.personalities_count)) * @sizeOf(u32); |
| 286 | 288 | total_size += (info.pages.items.len + 1) * @sizeOf(macho.unwind_info_section_header_index_entry); |
| 287 | 289 | total_size += info.lsdas.items.len * @sizeOf(macho.unwind_info_section_header_lsda_index_entry); |
| 288 | | total_size += info.pages.items.len * second_level_page_bytes; |
| 290 | for (info.pages.items) |page| { |
| 291 | total_size += page.size; |
| 292 | } |
| 289 | 293 | return total_size; |
| 290 | 294 | } |
| 291 | 295 | |
| ... | ... | @@ -318,18 +322,27 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void { |
| 318 | 322 | try writer.writeInt(u32, @intCast(sym.getGotAddress(macho_file) - seg.vmaddr), .little); |
| 319 | 323 | } |
| 320 | 324 | |
| 321 | | const pages_base_offset = @as(u32, @intCast(header.size - (info.pages.items.len * second_level_page_bytes))); |
| 325 | // Calculate total size of all pages |
| 326 | var total_pages_size: u32 = 0; |
| 327 | for (info.pages.items) |page| { |
| 328 | total_pages_size += page.size; |
| 329 | } |
| 330 | |
| 331 | const pages_base_offset = @as(u32, @intCast(header.size - total_pages_size)); |
| 322 | 332 | const lsda_base_offset = @as(u32, @intCast(pages_base_offset - |
| 323 | 333 | (info.lsdas.items.len * @sizeOf(macho.unwind_info_section_header_lsda_index_entry)))); |
| 324 | | for (info.pages.items, 0..) |page, i| { |
| 334 | |
| 335 | var page_offset: u32 = pages_base_offset; |
| 336 | for (info.pages.items) |page| { |
| 325 | 337 | assert(page.count > 0); |
| 326 | 338 | const rec = info.records.items[page.start].getUnwindRecord(macho_file); |
| 327 | 339 | try writer.writeStruct(@as(macho.unwind_info_section_header_index_entry, .{ |
| 328 | 340 | .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)), |
| 329 | | .secondLevelPagesSectionOffset = @as(u32, @intCast(pages_base_offset + i * second_level_page_bytes)), |
| 341 | .secondLevelPagesSectionOffset = page_offset, |
| 330 | 342 | .lsdaIndexArraySectionOffset = lsda_base_offset + |
| 331 | 343 | info.lsdas_lookup.items[page.start] * @sizeOf(macho.unwind_info_section_header_lsda_index_entry), |
| 332 | 344 | }), .little); |
| 345 | page_offset += page.size; |
| 333 | 346 | } |
| 334 | 347 | |
| 335 | 348 | const last_rec = info.records.items[info.records.items.len - 1].getUnwindRecord(macho_file); |
| ... | ... | @@ -350,16 +363,10 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void { |
| 350 | 363 | } |
| 351 | 364 | |
| 352 | 365 | for (info.pages.items) |page| { |
| 353 | | const start = writer.end; |
| 354 | 366 | try page.write(info, macho_file, &writer); |
| 355 | | const nwritten = writer.end - start; |
| 356 | | if (nwritten < second_level_page_bytes) { |
| 357 | | const padding = math.cast(usize, second_level_page_bytes - nwritten) orelse return error.Overflow; |
| 358 | | try writer.splatByteAll(0, padding); |
| 359 | | } |
| 360 | 367 | } |
| 361 | 368 | |
| 362 | | @memset(buffer[writer.end..], 0); |
| 369 | assert(writer.end == header.size); |
| 363 | 370 | } |
| 364 | 371 | |
| 365 | 372 | fn getOrPutPersonalityFunction(info: *UnwindInfo, ref: MachO.Ref) error{TooManyPersonalities}!u2 { |
| ... | ... | @@ -567,6 +574,7 @@ const Page = struct { |
| 567 | 574 | count: u16, |
| 568 | 575 | page_encodings: [max_compact_encodings]Encoding = undefined, |
| 569 | 576 | page_encodings_count: u9 = 0, |
| 577 | size: u32 = 0, |
| 570 | 578 | |
| 571 | 579 | fn appendPageEncoding(page: *Page, enc: Encoding) void { |
| 572 | 580 | assert(page.page_encodings_count <= max_compact_encodings); |
| ... | ... | @@ -585,6 +593,16 @@ const Page = struct { |
| 585 | 593 | return null; |
| 586 | 594 | } |
| 587 | 595 | |
| 596 | fn calcSize(page: Page) u32 { |
| 597 | return switch (page.kind) { |
| 598 | .regular => @sizeOf(macho.unwind_info_regular_second_level_page_header) + |
| 599 | @as(u32, page.count) * @sizeOf(macho.unwind_info_regular_second_level_entry), |
| 600 | .compressed => @sizeOf(macho.unwind_info_compressed_second_level_page_header) + |
| 601 | @as(u32, page.page_encodings_count) * @sizeOf(u32) + |
| 602 | @as(u32, page.count) * @sizeOf(u32), |
| 603 | }; |
| 604 | } |
| 605 | |
| 588 | 606 | const Format = struct { |
| 589 | 607 | page: Page, |
| 590 | 608 | info: UnwindInfo, |