Changeset 40eab9f in mainline for kernel/generic/src/debug/line.c


Ignore:
Timestamp:
2023-11-03T18:47:41Z (15 months ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
master, topic/msim-upgrade, topic/simplify-dev-export
Children:
b1397ab
Parents:
dcd8214
git-author:
Jiří Zárevúcky <zarevucky.jiri@…> (2023-11-03 18:46:22)
git-committer:
Jiří Zárevúcky <zarevucky.jiri@…> (2023-11-03 18:47:41)
Message:

Print symbol names and line numbers in stacktraces for init tasks

Only useful in select few situations, but useful nonetheless.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/debug/line.c

    rdcd8214 r40eab9f  
    297297}
    298298
    299 static void debug_line_program_header_parse(const uint8_t *data, const uint8_t *data_end, struct debug_line_program_header *hdr)
     299static void debug_line_program_header_parse(debug_sections_t *scs, const uint8_t *data, const uint8_t *data_end, struct debug_line_program_header *hdr)
    300300{
    301301        const uint8_t *unit_start = data;
     
    378378                hdr->v5.directories_end = data;
    379379
    380                 print_formatted_list("directories", hdr->v5.directories, hdr->v5.directories_end,
     380                print_formatted_list(scs, "directories", hdr->v5.directories, hdr->v5.directories_end,
    381381                    hdr->v5.directory_entry_format, hdr->v5.directory_entry_format_end, width);
    382382
     
    397397                hdr->v5.file_names_end = data;
    398398
    399                 print_formatted_list("file_names", hdr->v5.file_names, hdr->v5.file_names_end,
     399                print_formatted_list(scs, "file_names", hdr->v5.file_names, hdr->v5.file_names_end,
    400400                    hdr->v5.file_name_entry_format, hdr->v5.file_name_entry_format_end, width);
    401401        }
     
    463463}
    464464
    465 static const char *get_file_name_v5(struct debug_line_program_header *hdr, int file, int *dir)
     465static const char *get_file_name_v5(debug_sections_t *scs, struct debug_line_program_header *hdr, int file, int *dir)
    466466{
    467467        // DWARF5 has dynamic layout for file information, which is why
     
    493493                                if (form == DW_FORM_line_strp) {
    494494                                        uint64_t offset = read_uint(&fns, fns_end, hdr->width);
    495                                         if (offset < debug_line_str_size) {
    496                                                 filename = debug_line_str + offset;
     495                                        if (offset < scs->debug_line_str_size) {
     496                                                filename = scs->debug_line_str + offset;
    497497                                        }
    498498                                        continue;
     
    527527}
    528528
    529 static const char *get_file_name(struct debug_line_program_header *hdr, int file, int *dir)
     529static const char *get_file_name(debug_sections_t *scs, struct debug_line_program_header *hdr, int file, int *dir)
    530530{
    531531        switch (hdr->version) {
     
    534534                return get_file_name_v3(hdr, file, dir);
    535535        case 5:
    536                 return get_file_name_v5(hdr, file, dir);
     536                return get_file_name_v5(scs, hdr, file, dir);
    537537        default:
    538538                return NULL;
     
    558558}
    559559
    560 static const char *get_dir_name_v5(struct debug_line_program_header *hdr, int dir)
     560static const char *get_dir_name_v5(debug_sections_t *scs, struct debug_line_program_header *hdr, int dir)
    561561{
    562562        // TODO: basically a copypaste of get_file_name(). Try to deduplicate it.
     
    587587                                if (form == DW_FORM_line_strp) {
    588588                                        uint64_t offset = read_uint(&fns, fns_end, hdr->width);
    589                                         if (offset < debug_line_str_size) {
    590                                                 filename = debug_line_str + offset;
     589                                        if (offset < scs->debug_line_str_size) {
     590                                                filename = scs->debug_line_str + offset;
    591591                                        }
    592592                                        continue;
     
    604604}
    605605
    606 static const char *get_dir_name(struct debug_line_program_header *hdr, int dir)
     606static const char *get_dir_name(debug_sections_t *scs, struct debug_line_program_header *hdr, int dir)
    607607{
    608608        switch (hdr->version) {
     
    611611                return get_dir_name_v3(hdr, dir);
    612612        case 5:
    613                 return get_dir_name_v5(hdr, dir);
     613                return get_dir_name_v5(scs, hdr, dir);
    614614        default:
    615615                return NULL;
     
    617617}
    618618
    619 static const uint8_t *find_line_program(uintptr_t addr)
     619static const uint8_t *find_line_program(debug_sections_t *scs, uintptr_t addr)
    620620{
    621621        // TODO: use .debug_aranges to find the data quickly
     
    625625        const uint8_t *closest_prog = NULL;
    626626
    627         const uint8_t *debug_line_ptr = debug_line;
    628         const uint8_t *const debug_line_end = debug_line + debug_line_size;
     627        const uint8_t *debug_line_ptr = scs->debug_line;
     628        const uint8_t *const debug_line_end = scs->debug_line + scs->debug_line_size;
    629629
    630630        while (debug_line_ptr < debug_line_end) {
     
    633633                // Parse header
    634634                struct debug_line_program_header hdr = { };
    635                 debug_line_program_header_parse(prog, debug_line_end, &hdr);
     635                debug_line_program_header_parse(scs, prog, debug_line_end, &hdr);
    636636                assert(hdr.unit_end > debug_line_ptr);
    637637                assert(hdr.unit_end <= debug_line_end);
     
    678678                debug_line_program_advance(&lp);
    679679
    680                 if (!lp.truncated) {
    681                         // We check for the last address before addr, because addr
    682                         // is a return address and we want the call instruction.
    683                         if (lp.address >= addr && lp.op_advance >= op_index) {
    684                                 if (!first) {
    685                                         *file = last_file;
    686                                         *line = last_line;
    687                                         *column = last_column;
    688                                         return true;
    689                                 }
    690 
     680                if (lp.truncated)
     681                        continue;
     682
     683                /*
     684                 * Return previous entry when we pass the target address, because
     685                 * the address may not be aligned perfectly on instruction boundary.
     686                 */
     687                if (lp.address > addr || (lp.address == addr && lp.op_advance > op_index)) {
     688                        if (first) {
    691689                                // First address is already too large, skip to the next sequence.
    692690                                debug_line_program_skip_to_sequence_end(&lp);
    693                         }
    694 
    695                         last_file = lp.file;
    696                         last_line = lp.line;
    697                         last_column = lp.column;
    698                 }
     691                                continue;
     692                        }
     693
     694                        *file = last_file;
     695                        *line = last_line;
     696                        *column = last_column;
     697                        return true;
     698                }
     699
     700                last_file = lp.file;
     701                last_line = lp.line;
     702                last_column = lp.column;
    699703        }
    700704
     
    702706}
    703707
    704 bool debug_line_get_address_info(uintptr_t addr, int op_index, const char **file_name, const char **dir_name, int *line, int *column)
    705 {
    706         const uint8_t *data = find_line_program(addr);
     708bool debug_line_get_address_info(debug_sections_t *scs, uintptr_t addr, int op_index, const char **file_name, const char **dir_name, int *line, int *column)
     709{
     710        const uint8_t *data = find_line_program(scs, addr);
    707711        if (data == NULL) {
    708712                return false;
    709713        }
    710714
    711         const uint8_t *const debug_line_end = debug_line + debug_line_size;
     715        const uint8_t *const debug_line_end = scs->debug_line + scs->debug_line_size;
    712716
    713717        struct debug_line_program_header hdr = { };
    714         debug_line_program_header_parse(data, debug_line_end, &hdr);
     718        debug_line_program_header_parse(scs, data, debug_line_end, &hdr);
    715719        assert(hdr.unit_end > data);
    716720        assert(hdr.unit_end <= debug_line_end);
     
    727731
    728732        if (file >= 0)
    729                 *file_name = get_file_name(&hdr, file, &dir);
     733                *file_name = get_file_name(scs, &hdr, file, &dir);
    730734
    731735        if (dir >= 0)
    732                 *dir_name = get_dir_name(&hdr, dir);
     736                *dir_name = get_dir_name(scs, &hdr, dir);
    733737
    734738        return true;
Note: See TracChangeset for help on using the changeset viewer.