use callee info to disambiguate overlapping sibling inline sites

This commit is contained in:
Nikita Smith authored and Ryan Fleury committed 2026-08-21 10:56:19 -07:00
1 parent 8b52934c66
commit 3c719de3f5
3 files changed
+59 -11

No files matched your search

+1 -1
View File
@@ -2409,7 +2409,7 @@ lnk_link_image(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer
LNK_ObjLineMap *line_map = line_maps[obj->input_idx];
// is reference inline site?
LNK_InlineSite *inline_site = lnk_inline_site_from_section_offset(line_map, safe_cast_u32(section_number), reloc->apply_off);
LNK_InlineSite *inline_site = lnk_inline_site_from_section_offset(line_map, safe_cast_u32(section_number), reloc->apply_off, symbol);
if (inline_site && inline_site->name.size) {
CV_Line *line_inline = lnk_line_from_inline_site(inline_site, reloc->apply_off);
if (line_inline) {
+49 -3
View File
@@ -1349,6 +1349,20 @@ lnk_line_map_from_obj(Arena *arena, LNK_Obj *obj)
radsort(inline_site->lines, inline_site->line_count, cv_c13_voff_map_is_before);
}
}
} else if (symbol.kind == CV_SymKind_CALLEES) {
if (inline_site_stack_count && symbol.data.size >= sizeof(CV_SymFunctionList)) {
CV_SymFunctionList *func_list = (CV_SymFunctionList *)symbol.data.str;
U64 callee_count = Min(func_list->count, (symbol.data.size - sizeof(*func_list)) / sizeof(CV_ItemId));
CV_ItemId *callees = (CV_ItemId *)(func_list + 1);
LNK_InlineSite *inline_site = &map->inline_sites[inline_site_stack[inline_site_stack_count - 1]];
inline_site->callee_count = callee_count;
inline_site->callee_names = push_array(arena, String8, callee_count);
for EachIndex(callee_idx, callee_count) {
String8 *callee_name = hash_map_search_u64_string(&inlinee_hm, callees[callee_idx]);
inline_site->callee_names[callee_idx] = callee_name ? *callee_name : str8_zero();
}
}
} else if (symbol.kind == CV_SymKind_INLINESITE_END) {
if (inline_site_stack_count > 0) {
inline_site_stack_count -= 1;
@@ -1449,10 +1463,11 @@ lnk_lines_from_section_offset(LNK_ObjLineMap *map, U32 section_number, U32 offse
}
internal LNK_InlineSite *
lnk_inline_site_from_section_offset(LNK_ObjLineMap *map, U32 section_number, U32 offset)
lnk_inline_site_from_section_offset(LNK_ObjLineMap *map, U32 section_number, U32 offset, LNK_Symbol *callee_symbol)
{
U64 key = Compose64Bit(section_number, offset);
// find upper bound
U64 min = 0;
U64 opl = map->inline_range_count;
while (min < opl) {
@@ -1464,21 +1479,52 @@ lnk_inline_site_from_section_offset(LNK_ObjLineMap *map, U32 section_number, U32
}
}
LNK_InlineSite *site = 0;
// hacky demangle
String8 callee_name = callee_symbol ? callee_symbol->name : str8_zero();
if (str8_starts_with(callee_name, str8_lit("__imp_"))) {
callee_name = str8_skip(callee_name, 6);
}
if (str8_starts_with(callee_name, str8_lit("?"))) {
U64 name_opl = str8_find_needle(callee_name, 1, str8_lit("@"), 0);
callee_name = str8_substr(callee_name, r1u64(1, name_opl));
}
// scan back to the lower bound and match inline sites
LNK_InlineSite *site = 0;
LNK_InlineSite *callee_site = 0;
B32 callee_site_is_ambiguous = 0;
while (min > 0) {
LNK_InlineRange *range = &map->inline_ranges[--min];
if (key < range->key_max) {
LNK_InlineSite *candidate = &map->inline_sites[range->site_idx];
if (site == 0 || site->depth < candidate->depth) {
site = candidate;
}
for EachIndex(callee_idx, candidate->callee_count) {
String8 pdb_callee_name = candidate->callee_names[callee_idx];
if (str8_match(callee_name, pdb_callee_name, 0)) {
// candidate matches callee
if (callee_site == 0 || callee_site->depth < candidate->depth) {
callee_site = candidate;
callee_site_is_ambiguous = 0;
} else if (candidate->depth == callee_site->depth && candidate != callee_site) {
callee_site_is_ambiguous = 1;
}
break;
}
}
}
if (min == 0 || map->inline_ranges[min - 1].prefix_max <= key) {
break;
}
}
return site;
return (callee_site && !callee_site_is_ambiguous) ? callee_site : site;
}
internal CV_Line *
+9 -7
View File
@@ -115,12 +115,14 @@ typedef struct LNK_LineTable
typedef struct LNK_InlineSite
{
U32 parent_idx_plus_one;
U32 depth;
CV_ItemId inlinee;
String8 name;
U64 line_count;
CV_Line *lines;
U32 parent_idx_plus_one;
U32 depth;
CV_ItemId inlinee;
String8 name;
U64 callee_count;
String8 *callee_names;
U64 line_count;
CV_Line *lines;
} LNK_InlineSite;
typedef struct LNK_InlineRange
@@ -254,6 +256,6 @@ internal U32 lnk_symbol_from_section_offset(LNK_ObjSymbolMap *map
// CodeView map
internal LNK_ObjLineMap * lnk_line_map_from_obj(Arena *arena, LNK_Obj *obj);
internal CV_Line * lnk_lines_from_section_offset(LNK_ObjLineMap *map, U32 section_number, U32 offset, U64 *line_count_out);
internal LNK_InlineSite * lnk_inline_site_from_section_offset(LNK_ObjLineMap *map, U32 section_number, U32 offset);
internal LNK_InlineSite * lnk_inline_site_from_section_offset(LNK_ObjLineMap *map, U32 section_number, U32 offset, LNK_Symbol *callee_symbol);
internal CV_Line * lnk_line_from_inline_site(LNK_InlineSite *site, U32 offset);