Skip to content

Commit 9ed0af9

Browse files
committed
Output symbol names in wasm executable
1 parent 924e1b3 commit 9ed0af9

4 files changed

Lines changed: 154 additions & 14 deletions

File tree

src/wcc/wasm_linker.c

Lines changed: 105 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -300,17 +300,26 @@ static void renumber_symbols_wasmobj(WasmObj *wasmobj, uint32_t *defined_count)
300300
import_count[SIK_SYMTAB_FUNCTION] = wasmobj->import.functions->len;
301301
import_count[SIK_SYMTAB_DATA] = 0;
302302
import_count[SIK_SYMTAB_TABLE] = wasmobj->import.tables != NULL ? wasmobj->import.tables->len : 0;
303+
uint32_t data_count = 0;
303304
for (int i = 0; i < symtab->len; ++i) {
304305
SymbolInfo *sym = symtab->data[i];
305306
if (sym->flags & WASM_SYM_UNDEFINED)
306307
continue;
307308
switch (sym->kind) {
308309
default: assert(false); // Fallthrough to suppress warning.
309310
case SIK_SYMTAB_FUNCTION:
310-
case SIK_SYMTAB_DATA:
311311
case SIK_SYMTAB_TABLE:
312312
sym->combined_index = sym->local_index + defined_count[sym->kind] - import_count[sym->kind];
313313
break;
314+
case SIK_SYMTAB_DATA:
315+
{
316+
DataSegmentForLink *segment = &wasmobj->data.segments[sym->local_index];
317+
if (segment->is_bss)
318+
continue;
319+
sym->combined_index = data_count + defined_count[sym->kind] - import_count[sym->kind];
320+
++data_count;
321+
}
322+
break;
314323
case SIK_SYMTAB_GLOBAL:
315324
// Handled differently (just below).
316325
break;
@@ -330,7 +339,7 @@ static void renumber_symbols_wasmobj(WasmObj *wasmobj, uint32_t *defined_count)
330339

331340
// Increment count_table according to defined counts.
332341
defined_count[0] += wasmobj->func.count;
333-
defined_count[1] += wasmobj->data.count;
342+
defined_count[1] += data_count;
334343
// Assume table is not defined in wasmobj.
335344
}
336345

@@ -834,6 +843,7 @@ static void out_export_section(WasmLinker *linker, Table *exports) {
834843
data_uleb128(&exports_section, -1,
835844
sym->kind == SIK_SYMTAB_FUNCTION ? IMPORT_FUNC : IMPORT_GLOBAL); // export kind
836845
data_uleb128(&exports_section, -1, sym->combined_index); // export func index
846+
sym->flags |= WASM_SYM_EXPORTED;
837847
break;
838848
default:
839849
if (!linker->options.export_all)
@@ -936,15 +946,9 @@ static uint32_t out_data_section_wasmobj(WasmObj *wasmobj, DataStorage *datasec)
936946
uint32_t data_count = 0;
937947
for (uint32_t j = 0, count = wasmobj->data.count; j < count; ++j) {
938948
DataSegmentForLink *segment = &segments[j];
939-
uint32_t size = segment->size;
940-
const unsigned char *content = segment->content;
941-
uint32_t non_zero_size;
942-
for (non_zero_size = size; non_zero_size > 0; --non_zero_size) {
943-
if (content[non_zero_size - 1] != 0x00)
944-
break;
945-
}
946-
if (non_zero_size == 0) // BSS
949+
if (segment->is_bss)
947950
continue;
951+
uint32_t size = segment->size;
948952

949953
data_push(datasec, 0); // flags
950954
// Init (address).
@@ -953,8 +957,8 @@ static uint32_t out_data_section_wasmobj(WasmObj *wasmobj, DataStorage *datasec)
953957
data_leb128(datasec, -1, address);
954958
data_push(datasec, OP_END);
955959
// Content
956-
data_uleb128(datasec, -1, non_zero_size);
957-
data_append(datasec, segment->content, non_zero_size);
960+
data_uleb128(datasec, -1, size);
961+
data_append(datasec, segment->content, size);
958962
++data_count;
959963
}
960964
return data_count;
@@ -987,6 +991,92 @@ static void out_data_section(WasmLinker *linker) {
987991
fwrite(datasec.buf, datasec.len, 1, linker->ofp);
988992
}
989993

994+
enum CustomNameType {
995+
CN_MODULE,
996+
CN_FUNCTION,
997+
CN_LOCAL,
998+
CN_LABEL,
999+
CN_TYPE,
1000+
CN_TABLE,
1001+
CN_MEMORY,
1002+
CN_GLOBAL,
1003+
CN_ELEMENT,
1004+
CN_DATASEG,
1005+
};
1006+
1007+
static void out_custom_name_wasmobj(WasmObj *wasmobj, DataStorage *ds) {
1008+
Vector *symtab = wasmobj->linking.symtab;
1009+
Vector *funcs = new_vector();
1010+
Vector *datas = new_vector();
1011+
for (int j = 0; j < symtab->len; ++j) {
1012+
SymbolInfo *sym = symtab->data[j];
1013+
if (sym->flags & (WASM_SYM_UNDEFINED | WASM_SYM_EXPORTED))
1014+
continue;
1015+
switch (sym->kind) {
1016+
case SIK_SYMTAB_FUNCTION: vec_push(funcs, sym); break;
1017+
case SIK_SYMTAB_DATA:
1018+
if (sym->data.offset == 0) {
1019+
DataSegmentForLink *segment = &wasmobj->data.segments[sym->local_index];
1020+
if (!segment->is_bss) {
1021+
vec_push(datas, sym);
1022+
}
1023+
}
1024+
break;
1025+
default: break;
1026+
}
1027+
}
1028+
if (funcs->len != 0) {
1029+
data_push(ds, CN_FUNCTION);
1030+
data_open_chunk(ds);
1031+
data_uleb128(ds, -1, funcs->len);
1032+
for (int j = 0; j < funcs->len; ++j) {
1033+
SymbolInfo *sym = funcs->data[j];
1034+
data_uleb128(ds, -1, sym->combined_index);
1035+
data_string(ds, sym->name->chars, sym->name->bytes);
1036+
}
1037+
data_close_chunk(ds, -1);
1038+
}
1039+
if (datas->len != 0) {
1040+
data_push(ds, CN_DATASEG);
1041+
data_open_chunk(ds);
1042+
data_uleb128(ds, -1, datas->len);
1043+
for (int j = 0; j < datas->len; ++j) {
1044+
SymbolInfo *sym = datas->data[j];
1045+
data_uleb128(ds, -1, sym->combined_index);
1046+
data_string(ds, sym->name->chars, sym->name->bytes);
1047+
}
1048+
data_close_chunk(ds, -1);
1049+
}
1050+
free_vector(funcs);
1051+
free_vector(datas);
1052+
}
1053+
1054+
static void out_custom_section(WasmLinker *linker) {
1055+
DataStorage name_section;
1056+
static const char kName[] = "name";
1057+
data_init(&name_section);
1058+
data_open_chunk(&name_section);
1059+
data_string(&name_section, kName, sizeof(kName) - 1);
1060+
1061+
for (int i = 0; i < linker->files->len; ++i) {
1062+
File *file = linker->files->data[i];
1063+
switch (file->kind) {
1064+
case FK_WASMOBJ:
1065+
out_custom_name_wasmobj(file->wasmobj, &name_section);
1066+
break;
1067+
case FK_ARCHIVE:
1068+
FOREACH_FILE_ARCONTENT(file->archive, content, {
1069+
out_custom_name_wasmobj(content->obj, &name_section);
1070+
});
1071+
break;
1072+
}
1073+
}
1074+
1075+
data_close_chunk(&name_section, -1);
1076+
fputc(SEC_CUSTOM, linker->ofp);
1077+
fwrite(name_section.buf, name_section.len, 1, linker->ofp);
1078+
}
1079+
9901080
//
9911081

9921082
void linker_init(WasmLinker *linker) {
@@ -1197,6 +1287,9 @@ bool linker_emit_wasm(WasmLinker *linker, const char *ofn, Table *exports) {
11971287
// Data.
11981288
out_data_section(linker);
11991289

1290+
// Debug info
1291+
out_custom_section(linker);
1292+
12001293
fclose(ofp);
12011294

12021295
return true;

src/wcc/wasm_obj.c

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,16 @@ static void read_tag_section(WasmObj *wasmobj, unsigned char *p) {
218218
wasmobj->tag.count = num;
219219
}
220220

221+
inline static bool is_data_empty(const unsigned char *content, uint32_t size) {
222+
for (size_t i = 0; i < size; ++i) {
223+
if (content[i] != 0x00)
224+
return false;
225+
}
226+
return true;
227+
}
228+
221229
static void read_data_section(WasmObj *wasmobj, unsigned char *p) {
230+
unsigned char *top = p;
222231
DataSegmentForLink *segments = NULL;
223232
uint32_t count = read_uleb128(p, &p);
224233
segments = calloc_or_die(sizeof(*segments) * count);
@@ -229,8 +238,11 @@ static void read_data_section(WasmObj *wasmobj, unsigned char *p) {
229238
error("malformed data section");
230239
}
231240
uint32_t size = read_uleb128(p, &p);
241+
unsigned char *content = p;
232242
segment->size = size;
233-
segment->content = p;
243+
segment->content = content;
244+
segment->offset = content - top;
245+
segment->is_bss = is_data_empty(content, size);
234246

235247
p += segment->size;
236248
}
@@ -449,6 +461,24 @@ static void read_linking(WasmObj *wasmobj, unsigned char *p, unsigned char *end)
449461
}
450462
}
451463

464+
static DataSegmentForLink *find_target_data_segment(DataSegmentForLink *data_segments, uint32_t count, uint32_t offset) {
465+
int lo = -1, hi = count;
466+
while (hi - lo > 1) {
467+
const int m = lo + ((hi - lo) >> 1);
468+
DataSegmentForLink *p = &data_segments[m];
469+
if (p->offset + p->size < offset)
470+
lo = m;
471+
else
472+
hi = m;
473+
}
474+
if (hi >= (int)count)
475+
return NULL;
476+
DataSegmentForLink *p = &data_segments[hi];
477+
assert(offset >= p->offset);
478+
assert(offset < p->offset + p->size);
479+
return offset < p->offset + p->size ? p : NULL;
480+
}
481+
452482
static void read_reloc(WasmObj *wasmobj, unsigned char *p, int is_data) {
453483
uint32_t section_index = read_uleb128(p, &p);
454484
uint32_t count = read_uleb128(p, &p);
@@ -458,6 +488,10 @@ static void read_reloc(WasmObj *wasmobj, unsigned char *p, int is_data) {
458488
error("invalid section for relocation: section index=%d", section_index);
459489
}
460490

491+
DataSegmentForLink *data_segments = wasmobj->data.segments;
492+
uint32_t data_segment_count = wasmobj->data.count;
493+
assert(!is_data || data_segments != NULL);
494+
461495
RelocInfo *relocs = NULL;
462496
if (count > 0) {
463497
relocs = calloc_or_die(sizeof(*relocs) * count);
@@ -486,6 +520,12 @@ static void read_reloc(WasmObj *wasmobj, unsigned char *p, int is_data) {
486520
p->offset = offset;
487521
p->index = index;
488522
p->addend = addend;
523+
524+
if (is_data) { // Relocation is exist, so the correspoinding segment is not bss.
525+
DataSegmentForLink *ds = find_target_data_segment(data_segments, data_segment_count, offset);
526+
assert(ds != NULL);
527+
ds->is_bss = false;
528+
}
489529
}
490530
}
491531

src/wcc/wasm_obj.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ typedef struct DataSegmentForLink {
123123
unsigned char *content;
124124
uint32_t start;
125125
uint32_t size;
126+
uint32_t offset;
127+
bool is_bss;
126128
} DataSegmentForLink;
127129

128130
typedef struct TagData {

src/wcc/www/diswasm.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1554,7 +1554,12 @@ export class DisWasm {
15541554
const count = this.bufferReader.readUleb128()
15551555
const elements = [...Array(count)].map(_ => {
15561556
const index = this.bufferReader.readUleb128()
1557-
return this.getCustomName(CustomNameType.FUNCTION, index) ?? `${index}`
1557+
let customName = this.getCustomName(CustomNameType.FUNCTION, index)
1558+
if (customName == null && this.funcs.has(index)) {
1559+
const [_mod, name] = this.funcs.get(index)!
1560+
customName = `\$${name}`
1561+
}
1562+
return customName ?? `${index}`
15581563
})
15591564
this.log(`(elem (i32.const ${start}) func ${elements.join(' ')}) ;; ${i}`)
15601565
}

0 commit comments

Comments
 (0)