Skip to content

Commit b2eeb43

Browse files
committed
PDB workie
1 parent a1b4b09 commit b2eeb43

2 files changed

Lines changed: 168 additions & 17 deletions

File tree

linker/linker.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,6 @@ bool tb_linker_layout(TB_Linker* l) {
10181018
DynArray(TB_LinkerSection*) sections = NULL;
10191019
CUIK_TIMED_BLOCK("sort sections") {
10201020
size_t num = 0;
1021-
10221021
nbhs_for(e, &l->sections) {
10231022
TB_LinkerSection* s = *e;
10241023
if (s->generic_flags & TB_LINKER_SECTION_DISCARD) {
@@ -1041,7 +1040,7 @@ bool tb_linker_layout(TB_Linker* l) {
10411040
}
10421041
}
10431042

1044-
// printf("%.*s: %zu -> %zu\n", (int) s->name.length, s->name.data, piece_count, j);
1043+
// printf("%.*s: %zu -> %zu\n", (int) s->name.length, s->name.data, piece_count, dyn_array_length(array_form));
10451044
}
10461045

10471046
if (dyn_array_length(array_form) == 0) {
@@ -1268,11 +1267,6 @@ void tb_linker_push_named(TB_Linker* l, const char* name) {
12681267
}
12691268

12701269
bool tb_linker_push_piece(TB_Linker* l, TB_LinkerSectionPiece* p) {
1271-
static const char sss[] = "api-ms-win-core-calendar-l1-1-0.dll";
1272-
if (p->obj->name.length == sizeof(sss)-1 && memcmp((const char*) p->obj->name.data, sss, sizeof(sss)-1) == 0) {
1273-
__debugbreak();
1274-
}
1275-
12761270
if (p->size == 0 || (p->flags & TB_LINKER_PIECE_LIVE) || (p->parent->generic_flags & TB_LINKER_SECTION_DISCARD)) {
12771271
return false;
12781272
}

linker/pe_linker.c

Lines changed: 167 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,73 @@
77
#include <tb_coff.h>
88
#include <file_map.h>
99

10-
enum { IMP_PREFIX_LEN = sizeof("__imp_") - 1 };
10+
enum {
11+
IMP_PREFIX_LEN = sizeof("__imp_") - 1,
12+
PDB_BLOCK_SIZE = 4096,
13+
};
1114

1215
typedef struct {
1316
uint32_t offset;
1417
TB_LinkerSegment* segment;
1518
} PE_BaseReloc;
1619

20+
// https://llvm.org/docs/PDB/MsfFile.html#the-stream-directory
21+
typedef struct {
22+
char file_magic[32];
23+
uint32_t block_size;
24+
uint32_t free_block_map_block;
25+
uint32_t num_blocks;
26+
uint32_t num_directory_bytes;
27+
uint32_t unknown;
28+
uint32_t dir_blocks[];
29+
} PDB_SuperBlock;
30+
31+
// serialized form
32+
typedef struct {
33+
uint32_t version;
34+
uint32_t signature;
35+
uint32_t age;
36+
uint32_t unique_id[4];
37+
} PDB_InfoHeader;
38+
39+
// https://llvm.org/docs/PDB/DbiStream.html
40+
typedef struct {
41+
// I have no idea why they didn't make this
42+
// part of the streams consistent btw. Info
43+
// does ver+sign+age, here it's sign+ver+age
44+
uint32_t signature;
45+
uint32_t version;
46+
uint32_t age;
47+
48+
uint16_t global_stream; // StreamIndex
49+
uint16_t build_num;
50+
51+
uint16_t public_stream; // StreamIndex
52+
uint16_t pdb_dll_version;
53+
uint16_t sym_record_stream; // StreamIndex
54+
uint16_t pdb_dll_rebuild;
55+
uint32_t mod_info_size;
56+
uint32_t section_contrib_size;
57+
uint32_t section_map_size;
58+
uint32_t source_info_size;
59+
uint32_t type_server_size;
60+
uint32_t mfc_type_server; // StreamIndex
61+
uint32_t optional_debug_header_size;
62+
uint32_t ec_subsystem_size;
63+
64+
uint16_t flags;
65+
uint16_t machine;
66+
67+
uint32_t pad;
68+
uint8_t data[];
69+
} PDB_DBIHeader;
70+
71+
typedef struct {
72+
size_t size;
73+
// We assume that all blocks are contiguous for now
74+
size_t first_block;
75+
} DebugStream;
76+
1777
typedef struct {
1878
TB_Linker* linker;
1979
TB_LinkerObject* lib;
@@ -427,11 +487,6 @@ void pe_append_object(TPool* pool, void** args) {
427487

428488
uint64_t order = obj->time;
429489
CUIK_TIMED_BLOCK("parse sections") {
430-
if (strsuffix(obj->name.data, "api-ms-win-core-calendar-l1-1-0.dll", obj->name.length)) {
431-
assert(parser.section_count != 0);
432-
printf("ZZZ %zu\n", parser.section_count);
433-
}
434-
435490
FOR_N(i, 0, parser.section_count) {
436491
TB_ObjectSection* restrict s = &sections[i];
437492
tb_coff_parse_section(&parser, i, s);
@@ -478,10 +533,6 @@ void pe_append_object(TPool* pool, void** args) {
478533
pdata_piece = p;
479534
}
480535
}
481-
482-
if (strsuffix(obj->name.data, "api-ms-win-core-calendar-l1-1-0.dll", obj->name.length)) {
483-
printf("AAA %.*s %#x\n", (int) s->name.length, s->name.data, p->flags);
484-
}
485536
}
486537
}
487538

@@ -1195,6 +1246,8 @@ static DynArray(PE_BaseReloc) find_base_relocs(TB_Linker* l) {
11951246
return base_relocs;
11961247
}
11971248

1249+
#define WRITE8(data) (output[write_pos++] = (data))
1250+
#define WRITE32(data) (memcpy(&output[write_pos], &(uint32_t){ data }, 4), write_pos += (4))
11981251
#define WRITE(data, size) (memcpy(&output[write_pos], data, size), write_pos += (size))
11991252
static bool pe_export(TB_Linker* l, const char* file_name) {
12001253
cuikperf_region_start("linker", NULL);
@@ -1538,9 +1591,113 @@ static bool pe_export(TB_Linker* l, const char* file_name) {
15381591
close_file_map(&fm);
15391592
}
15401593

1594+
CUIK_TIMED_BLOCK("pdb output") {
1595+
DynArray(DebugStream*) streams = dyn_array_create(DebugStream*, 8);
1596+
FOR_N(i, 0, 6) {
1597+
DebugStream* s = tb_arena_alloc(&linker_perm_arena, sizeof(DebugStream));
1598+
s->size = 0;
1599+
if (i == 1) {
1600+
s->size = 71; // Info stream
1601+
} else if (i == 3) {
1602+
s->size = sizeof(PDB_DBIHeader);
1603+
}
1604+
dyn_array_put(streams, s);
1605+
}
1606+
1607+
size_t blocks_needed = 5;
1608+
dyn_array_for(i, streams) {
1609+
streams[i]->first_block = blocks_needed;
1610+
blocks_needed += (streams[i]->size + PDB_BLOCK_SIZE - 1) / PDB_BLOCK_SIZE;
1611+
}
1612+
1613+
// 0 1 2 3 4 5 6 7 8
1614+
// Superblock Free0 Free1 Dirs Headers Block Block Block Block
1615+
size_t pdb_size = blocks_needed*PDB_BLOCK_SIZE;
1616+
FileMap fm = open_file_map_write("a.pdb", pdb_size);
1617+
if (fm.data == NULL) {
1618+
printf("tblink: could not open file! %s", "a.pdb");
1619+
return false;
1620+
}
1621+
1622+
size_t write_pos = 0;
1623+
uint8_t* output = fm.data;
1624+
1625+
PDB_SuperBlock super = {
1626+
.file_magic = "Microsoft C/C++ MSF 7.00\r\n\x1A\x44\x53\0\0",
1627+
.block_size = PDB_BLOCK_SIZE,
1628+
.free_block_map_block = 1,
1629+
.num_blocks = blocks_needed,
1630+
.num_directory_bytes = 4 + dyn_array_length(streams)*8,
1631+
};
1632+
1633+
// SuperBlock + directory page blocks
1634+
WRITE(&super, sizeof(super));
1635+
WRITE32(3);
1636+
1637+
// Block3: Directory
1638+
write_pos = 3*PDB_BLOCK_SIZE;
1639+
WRITE32(4);
1640+
1641+
// Block4: Stream Headers
1642+
write_pos = 4*PDB_BLOCK_SIZE;
1643+
WRITE32(dyn_array_length(streams));
1644+
dyn_array_for(i, streams) { WRITE32(streams[i]->size); }
1645+
dyn_array_for(i, streams) {
1646+
size_t block_count = (streams[i]->size + PDB_BLOCK_SIZE - 1) / PDB_BLOCK_SIZE;
1647+
FOR_N(j, 0, block_count) {
1648+
WRITE32(streams[i]->first_block + j);
1649+
}
1650+
}
1651+
1652+
dyn_array_for(i, streams) {
1653+
size_t start = write_pos = streams[i]->first_block*PDB_BLOCK_SIZE;
1654+
if (i == 1) {
1655+
PDB_InfoHeader stream = {
1656+
.version = 20000404, // VC70
1657+
};
1658+
WRITE(&stream, sizeof(stream));
1659+
1660+
// PDB Names streams
1661+
WRITE32(sizeof("/names"));
1662+
WRITE("/names", sizeof("/names"));
1663+
1664+
// https://llvm.org/docs/PDB/HashTable.html
1665+
// There's a really weird hash map stuffed here rather than
1666+
// some direct stream indices but whatever, my job isn't to
1667+
// question microsoft, that's a hobby, my job is to put up
1668+
// with microsoft.
1669+
//
1670+
// Size & Capacity
1671+
WRITE32(1);
1672+
WRITE32(1);
1673+
// Present Bit Vector
1674+
WRITE32(1);
1675+
WRITE32(1);
1676+
// Deleted Bit Vector
1677+
WRITE32(1);
1678+
WRITE32(0);
1679+
// Entries
1680+
WRITE32(0);
1681+
WRITE32(5);
1682+
} else if (i == 3) {
1683+
PDB_DBIHeader stream = {
1684+
.signature = -1,
1685+
.version = 19990903, // VC70
1686+
.machine = 0xD0,
1687+
};
1688+
WRITE(&stream, sizeof(stream));
1689+
}
1690+
assert(write_pos - start == streams[i]->size);
1691+
}
1692+
1693+
close_file_map(&fm);
1694+
}
1695+
15411696
cuikperf_region_end();
15421697
return true;
15431698
}
1699+
#undef WRITE32
1700+
#undef WRITE8
15441701
#undef WRITE
15451702

15461703
TB_LinkerVtbl tb__linker_pe = {

0 commit comments

Comments
 (0)