History

win32: pe dwarf sections & option -g.pdb

On windows, create a .pdb file with option "-g.pdb" Such executables created by tcc can be debugged with "ollydbg" or "x64dbg" This currently relies on the 3rd party tool cv2pdb from https://github.com/rainers/cv2pdb which again relies on mspdbsrv.exe mspdbcore.dll msobj80.dll mspdb80.dll from a MSVC installation. cv2pdb.exe + the ms* files may be put in the path or in the same directory as tcc.exe.

grischka committed 3 years ago

Commit 45204541 parent cd75ca65 files · +107 −43Browse files

Unified · Split

5 files
  1. libtcc.c +4 −1
  2. tcc.c +3 −0
  3. tccdbg.c +1 −1
  4. tccgen.c +28 −29
  5. tccpe.c +71 −12
libtcc.c+4−1
@@ -1976,9 +1976,12 @@ dorun: · 1975 unmodified lines
1976 case TCC_OPTION_g:1976 case TCC_OPTION_g:
1977 s->do_debug = 1;1977 s->do_debug = 1;
1978 s->dwarf = DWARF_VERSION;1978 s->dwarf = DWARF_VERSION;
1979
1980 if (strstart("dwarf", &optarg))1979 if (strstart("dwarf", &optarg))
1981 s->dwarf = (*optarg) ? (0 - atoi(optarg)) : DEFAULT_DWARF_VERSION;1980 s->dwarf = (*optarg) ? (0 - atoi(optarg)) : DEFAULT_DWARF_VERSION;
1981#ifdef TCC_TARGET_PE
1982 else if (0 == strcmp(".pdb", optarg))
1983 s->dwarf = 5, s->do_debug |= 16;
1984#endif
1982 break;1985 break;
1983 case TCC_OPTION_c:1986 case TCC_OPTION_c:
1984 x = TCC_OUTPUT_OBJ;1987 x = TCC_OUTPUT_OBJ;
tcc.c+3−0
@@ -59,6 +59,9 @@ static const char help[] = · 58 unmodified lines
59 "Debugger options:\n"59 "Debugger options:\n"
60 " -g generate stab runtime debug info\n"60 " -g generate stab runtime debug info\n"
61 " -gdwarf[-x] generate dwarf runtime debug info\n"61 " -gdwarf[-x] generate dwarf runtime debug info\n"
62#ifdef TCC_TARGET_PE
63 " -g.pdb create .pdb debug database\n"
64#endif
62#ifdef CONFIG_TCC_BCHECK65#ifdef CONFIG_TCC_BCHECK
63 " -b compile with built-in memory and bounds checker (implies -g)\n"66 " -b compile with built-in memory and bounds checker (implies -g)\n"
64#endif67#endif
tccdbg.c+1−1
@@ -1086,7 +1086,7 @@ ST_FUNC void tcc_debug_line(TCCState *s1) · 1085 unmodified lines
1086 1086
1087 if (!s1->do_debug)1087 if (!s1->do_debug)
1088 return;1088 return;
1089 if (cur_text_section != text_section)1089 if (cur_text_section != text_section || nocode_wanted)
1090 return;1090 return;
1091 f = put_new_file(s1);1091 f = put_new_file(s1);
1092 if (!f)1092 if (!f)
tccgen.c+28−29
@@ -5500,25 +5500,12 @@ ST_FUNC void unary(void) · 5499 unmodified lines
5500 goto tok_identifier;5500 goto tok_identifier;
5501 /* fall thru */5501 /* fall thru */
5502 case TOK___FUNC__:5502 case TOK___FUNC__:
5503 {5503 tok = TOK_STR;
5504 Section *sec;5504 cstr_reset(&tokcstr);
5505 int len;5505 cstr_cat(&tokcstr, funcname, 0);
5506 /* special function name identifier */5506 tokc.str.size = tokcstr.size;
5507 len = strlen(funcname) + 1;5507 tokc.str.data = tokcstr.data;
5508 /* generate char[len] type */5508 goto case_TOK_STR;
5509 type.t = char_type.t;
5510 if (tcc_state->warn_write_strings & WARN_ON)
5511 type.t |= VT_CONSTANT;
5512 mk_pointer(&type);
5513 type.t |= VT_ARRAY;
5514 type.ref->c = len;
5515 sec = rodata_section;
5516 vpush_ref(&type, sec, sec->data_offset, len);
5517 if (!NODATA_WANTED)
5518 memcpy(section_ptr_add(sec, len), funcname, len);
5519 next();
5520 }
5521 break;
5522 case TOK_LSTR:5509 case TOK_LSTR:
5523#ifdef TCC_TARGET_PE5510#ifdef TCC_TARGET_PE
5524 t = VT_SHORT | VT_UNSIGNED;5511 t = VT_SHORT | VT_UNSIGNED;
@@ -5527,6 +5514,7 @@ ST_FUNC void unary(void) · 2 unmodified lines
5527#endif5514#endif
5528 goto str_init;5515 goto str_init;
5529 case TOK_STR:5516 case TOK_STR:
5517 case_TOK_STR:
5530 /* string parsing */5518 /* string parsing */
5531 t = char_type.t;5519 t = char_type.t;
5532 str_init:5520 str_init:
@@ -7767,7 +7755,7 @@ static void decl_initializer(init_params *p, CType *type, unsigned long c, int f · 2234 unmodified lines
7767 CType *t1;7755 CType *t1;
7768 7756
7769 /* generate line number info */7757 /* generate line number info */
7770 if (debug_modes && !p->sec)7758 if (debug_modes && !(flags & DIF_SIZE_ONLY) && !p->sec)
7771 tcc_debug_line(tcc_state), tcc_tcov_check_line (tcc_state, 1);7759 tcc_debug_line(tcc_state), tcc_tcov_check_line (tcc_state, 1);
7772 7760
7773 if (!(flags & DIF_HAVE_ELEM) && tok != '{' &&7761 if (!(flags & DIF_HAVE_ELEM) && tok != '{' &&
@@ -8288,50 +8276,60 @@ static void gen_function(Sym *sym) · 514 unmodified lines
8288 struct scope f = { 0 };8276 struct scope f = { 0 };
8289 cur_scope = root_scope = &f;8277 cur_scope = root_scope = &f;
8290 nocode_wanted = 0;8278 nocode_wanted = 0;
8279
8291 ind = cur_text_section->data_offset;8280 ind = cur_text_section->data_offset;
8292 if (sym->a.aligned) {8281 if (sym->a.aligned) {
8293 size_t newoff = section_add(cur_text_section, 0,8282 size_t newoff = section_add(cur_text_section, 0,
8294 1 << (sym->a.aligned - 1));8283 1 << (sym->a.aligned - 1));
8295 gen_fill_nops(newoff - ind);8284 gen_fill_nops(newoff - ind);
8296 }8285 }
8286
8287 funcname = get_tok_str(sym->v, NULL);
8288 func_ind = ind;
8289 func_vt = sym->type.ref->type;
8290 func_var = sym->type.ref->f.func_type == FUNC_ELLIPSIS;
8291
8297 /* NOTE: we patch the symbol size later */8292 /* NOTE: we patch the symbol size later */
8298 put_extern_sym(sym, cur_text_section, ind, 0);8293 put_extern_sym(sym, cur_text_section, ind, 0);
8294
8299 if (sym->type.ref->f.func_ctor)8295 if (sym->type.ref->f.func_ctor)
8300 add_array (tcc_state, ".init_array", sym->c);8296 add_array (tcc_state, ".init_array", sym->c);
8301 if (sym->type.ref->f.func_dtor)8297 if (sym->type.ref->f.func_dtor)
8302 add_array (tcc_state, ".fini_array", sym->c);8298 add_array (tcc_state, ".fini_array", sym->c);
8303 8299
8304 funcname = get_tok_str(sym->v, NULL);
8305 func_ind = ind;
8306 func_vt = sym->type.ref->type;
8307 func_var = sym->type.ref->f.func_type == FUNC_ELLIPSIS;
8308
8309 /* put debug symbol */8300 /* put debug symbol */
8310 tcc_debug_funcstart(tcc_state, sym);8301 tcc_debug_funcstart(tcc_state, sym);
8302
8311 /* push a dummy symbol to enable local sym storage */8303 /* push a dummy symbol to enable local sym storage */
8312 sym_push2(&local_stack, SYM_FIELD, 0, 0);8304 sym_push2(&local_stack, SYM_FIELD, 0, 0);
8313 local_scope = 1; /* for function parameters */8305 local_scope = 1; /* for function parameters */
8314 gfunc_prolog(sym);8306 gfunc_prolog(sym);
8315 tcc_debug_prolog_epilog(tcc_state, 0);8307 tcc_debug_prolog_epilog(tcc_state, 0);
8308
8316 local_scope = 0;8309 local_scope = 0;
8317 rsym = 0;8310 rsym = 0;
8318 clear_temp_local_var_list();8311 clear_temp_local_var_list();
8319 func_vla_arg(sym);8312 func_vla_arg(sym);
8320 block(0);8313 block(0);
8321 gsym(rsym);8314 gsym(rsym);
8315
8322 nocode_wanted = 0;8316 nocode_wanted = 0;
8323 /* reset local stack */8317 /* reset local stack */
8324 pop_local_syms(NULL, 0);8318 pop_local_syms(NULL, 0);
8325 tcc_debug_prolog_epilog(tcc_state, 1);8319 tcc_debug_prolog_epilog(tcc_state, 1);
8326 gfunc_epilog();8320 gfunc_epilog();
8321
8322 /* end of function */
8323 tcc_debug_funcend(tcc_state, ind - func_ind);
8324
8325 /* patch symbol size */
8326 elfsym(sym)->st_size = ind - func_ind;
8327
8327 cur_text_section->data_offset = ind;8328 cur_text_section->data_offset = ind;
8328 local_scope = 0;8329 local_scope = 0;
8329 label_pop(&global_label_stack, NULL, 0);8330 label_pop(&global_label_stack, NULL, 0);
8330 sym_pop(&all_cleanups, NULL, 0);8331 sym_pop(&all_cleanups, NULL, 0);
8331 /* patch symbol size */8332
8332 elfsym(sym)->st_size = ind - func_ind;
8333 /* end of function */
8334 tcc_debug_funcend(tcc_state, ind - func_ind);
8335 /* It's better to crash than to generate wrong code */8333 /* It's better to crash than to generate wrong code */
8336 cur_text_section = NULL;8334 cur_text_section = NULL;
8337 funcname = ""; /* for safety */8335 funcname = ""; /* for safety */
@@ -8341,6 +8339,7 @@ static void gen_function(Sym *sym) · 3 unmodified lines
8341 func_ind = -1;8339 func_ind = -1;
8342 nocode_wanted = DATA_ONLY_WANTED;8340 nocode_wanted = DATA_ONLY_WANTED;
8343 check_vstack();8341 check_vstack();
8342
8344 /* do this after funcend debug info */8343 /* do this after funcend debug info */
8345 next();8344 next();
8346}8345}
tccpe.c+71−12
@@ -301,8 +301,7 @@ enum { · 300 unmodified lines
301 sec_pdata ,301 sec_pdata ,
302 sec_other ,302 sec_other ,
303 sec_rsrc ,303 sec_rsrc ,
304 sec_stab ,304 sec_debug ,
305 sec_stabstr ,
306 sec_reloc ,305 sec_reloc ,
307 sec_last306 sec_last
308};307};
@@ -475,9 +474,9 @@ struct pe_file { · 166 unmodified lines
475 unsigned pos;474 unsigned pos;
476};475};
477 476
478static int pe_fwrite(void *data, int len, struct pe_file *pf)477static int pe_fwrite(const void *data, int len, struct pe_file *pf)
479{478{
480 WORD *p = data;479 const WORD *p = data;
481 DWORD sum;480 DWORD sum;
482 int ret, i;481 int ret, i;
483 pf->pos += (ret = fwrite(data, 1, len, pf->op));482 pf->pos += (ret = fwrite(data, 1, len, pf->op));
@@ -502,6 +501,51 @@ static void pe_fpad(struct pe_file *pf, DWORD new_pos) · 18 unmodified lines
502 pf->pos = new_pos;501 pf->pos = new_pos;
503}502}
504 503
504/*----------------------------------------------------------------------------*/
505/* PE-DWARF/COFF support
506 does not work with a mingw-gdb really but works with cv2pdb
507 (https://github.com/rainers/cv2pdb) */
508
509#define N_COFF_SYMS 0
510
511static const char dwarf_secs[] =
512{
513 ".debug_info\0"
514 ".debug_abbrev\0"
515 ".debug_line\0"
516 ".debug_aranges\0"
517 ".debug_str\0"
518 ".debug_line_str\0"
519};
520
521static const unsigned coff_strtab_size = 4 + sizeof dwarf_secs - 1;
522
523static int pe_put_long_secname(char *secname, const char *name)
524{
525 const char *d = dwarf_secs;
526 do {
527 if (0 == strcmp(d, name)) {
528 sprintf(secname, "/%d", (int)(d - dwarf_secs + 4));
529 return 1;
530 }
531 d = strchr(d, 0) + 1;
532 } while (*d);
533 return 0;
534}
535
536static void pe_create_pdb(TCCState *s1, const char *exename)
537{
538 char buf[300]; int r;
539 snprintf(buf, sizeof buf, "cv2pdb.exe %s", exename);
540 r = system(buf);
541 strcpy(tcc_fileextension(strcpy(buf, exename)), ".pdb");
542 if (r) {
543 tcc_error_noabort("could not create '%s'\n(need working cv2pdb from https://github.com/rainers/cv2pdb)", buf);
544 } else if (s1->verbose) {
545 printf("<- %s\n", buf);
546 }
547}
548
505/*----------------------------------------------------------------------------*/549/*----------------------------------------------------------------------------*/
506static int pe_write(struct pe_info *pe)550static int pe_write(struct pe_info *pe)
507{551{
@@ -616,6 +660,7 @@ static int pe_write(struct pe_info *pe) · 108 unmodified lines
616 struct section_info *si;660 struct section_info *si;
617 IMAGE_SECTION_HEADER *psh;661 IMAGE_SECTION_HEADER *psh;
618 TCCState *s1 = pe->s1;662 TCCState *s1 = pe->s1;
663 int need_strtab = 0;
619 664
620 pf.op = fopen(pe->filename, "wb");665 pf.op = fopen(pe->filename, "wb");
621 if (NULL == pf.op)666 if (NULL == pf.op)
@@ -686,6 +731,8 @@ static int pe_write(struct pe_info *pe) · 64 unmodified lines
686 }731 }
687 732
688 memcpy(psh->Name, sh_name, umin(strlen(sh_name), sizeof psh->Name));733 memcpy(psh->Name, sh_name, umin(strlen(sh_name), sizeof psh->Name));
734 if (si->cls == sec_debug)
735 need_strtab += pe_put_long_secname(psh->Name, sh_name);
689 736
690 psh->Characteristics = si->pe_flags;737 psh->Characteristics = si->pe_flags;
691 psh->VirtualAddress = addr;738 psh->VirtualAddress = addr;
@@ -715,7 +762,10 @@ static int pe_write(struct pe_info *pe) · 23 unmodified lines
715 if (PE_DLL == pe->type)762 if (PE_DLL == pe->type)
716 pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL;763 pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL;
717 pe_header.filehdr.Characteristics |= pe->s1->pe_characteristics;764 pe_header.filehdr.Characteristics |= pe->s1->pe_characteristics;
718 765 if (need_strtab) {
766 pe_header.filehdr.PointerToSymbolTable = file_offset;
767 pe_header.filehdr.NumberOfSymbols = N_COFF_SYMS;
768 }
719 pe_fwrite(&pe_header, sizeof pe_header, &pf);769 pe_fwrite(&pe_header, sizeof pe_header, &pf);
720 for (i = 0; i < pe->sec_count; ++i)770 for (i = 0; i < pe->sec_count; ++i)
721 pe_fwrite(&pe->sec_info[i]->ish, sizeof(IMAGE_SECTION_HEADER), &pf);771 pe_fwrite(&pe->sec_info[i]->ish, sizeof(IMAGE_SECTION_HEADER), &pf);
@@ -736,6 +786,13 @@ static int pe_write(struct pe_info *pe) · 14 unmodified lines
736 pe_fpad(&pf, file_offset);786 pe_fpad(&pf, file_offset);
737 }787 }
738 788
789 if (need_strtab) {
790 /* create a tiny COFF string table with the long section names */
791 pe_fwrite(&coff_strtab_size, sizeof coff_strtab_size, &pf);
792 pe_fwrite(dwarf_secs, sizeof dwarf_secs - 1, &pf);
793 file_offset = pf.pos;
794 }
795
739 pf.sum += file_offset;796 pf.sum += file_offset;
740 fseek(pf.op, offsetof(struct pe_header, opthdr.CheckSum), SEEK_SET);797 fseek(pf.op, offsetof(struct pe_header, opthdr.CheckSum), SEEK_SET);
741 pe_fwrite(&pf.sum, sizeof (DWORD), &pf);798 pe_fwrite(&pf.sum, sizeof (DWORD), &pf);
@@ -750,6 +807,8 @@ static int pe_write(struct pe_info *pe) · 8 unmodified lines
750 if (pe->s1->verbose)807 if (pe->s1->verbose)
751 printf("<- %s (%u bytes)\n", pe->filename, (unsigned)file_offset);808 printf("<- %s (%u bytes)\n", pe->filename, (unsigned)file_offset);
752 809
810 if (s1->do_debug & 16)
811 pe_create_pdb(s1, pe->filename);
753 return 0;812 return 0;
754}813}
755 814
@@ -1072,12 +1131,12 @@ static int pe_section_class(Section *s) · 316 unmodified lines
1072 type = s->sh_type;1131 type = s->sh_type;
1073 flags = s->sh_flags;1132 flags = s->sh_flags;
1074 name = s->name;1133 name = s->name;
1075 if (0 == memcmp(name, ".stab", 5)) {1134
1076 if (0 == s->s1->do_debug)1135 if (0 == memcmp(name, ".stab", 5) || 0 == memcmp(name, ".debug_", 7)) {
1077 return sec_last;1136 if (s->s1->do_debug)
1078 return name[5] ? sec_stabstr : sec_stab;1137 return sec_debug;
1079 }1138
1080 if (flags & SHF_ALLOC) {1139 } else if (flags & SHF_ALLOC) {
1081 if (type == SHT_PROGBITS1140 if (type == SHT_PROGBITS
1082 || type == SHT_INIT_ARRAY1141 || type == SHT_INIT_ARRAY
1083 || type == SHT_FINI_ARRAY) {1142 || type == SHT_FINI_ARRAY) {
@@ -1135,7 +1194,7 @@ static int pe_assign_addresses (struct pe_info *pe) · 51 unmodified lines
1135 if (PE_MERGE_DATA && c == sec_bss)1194 if (PE_MERGE_DATA && c == sec_bss)
1136 c = sec_data;1195 c = sec_data;
1137 1196
1138 if (si && c == si->cls) {1197 if (si && c == si->cls && c != sec_debug) {
1139 /* merge with previous section */1198 /* merge with previous section */
1140 s->sh_addr = addr = ((addr - 1) | (16 - 1)) + 1;1199 s->sh_addr = addr = ((addr - 1) | (16 - 1)) + 1;
1141 } else {1200 } else {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t