Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 94 additions & 105 deletions output/codeview.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,20 @@ const struct dfmt df_cv8 = {
NULL, /* .debug_mmacros */
null_debug_directive, /* .debug_directive */
cv8_typevalue, /* .debug_typevalue */
cv8_output, /* .debug_output */
NULL, /* .debug_output */
cv8_cleanup, /* .cleanup */
NULL /* pragma list */
};

/*******************************************************************************
* dfmt callbacks
******************************************************************************/
struct sect_lines
{
struct SAA *lines;
uint32_t num_lines;
};

struct source_file;

struct source_file {
Expand All @@ -59,8 +65,7 @@ struct source_file {
uint32_t filetbl_off;
uint32_t sourcetbl_off;

struct SAA *lines;
uint32_t num_lines;
struct sect_lines *sects;

unsigned char md5sum[MD5_HASHBYTES];
};
Expand Down Expand Up @@ -108,18 +113,13 @@ struct cv8_state {
int symbol_sect;
int type_sect;

uint32_t text_offset;

struct source_file *source_files, **source_files_tail;
const char *last_filename;
struct source_file *last_source_file;
struct hash_table file_hash;
unsigned num_files;
uint32_t total_filename_len;


unsigned total_lines;

struct SAA *symbols;
struct cv8_symbol *last_sym;
unsigned num_syms[SYMTYPE_MAX];
Expand All @@ -143,70 +143,68 @@ static void cv8_init(void)
cv8_state.symbol_sect = coff_make_section(".debug$S", sect_flags);
cv8_state.type_sect = coff_make_section(".debug$T", sect_flags);

cv8_state.text_offset = 0;

cv8_state.source_files = NULL;
cv8_state.source_files_tail = &cv8_state.source_files;

cv8_state.num_files = 0;
cv8_state.total_filename_len = 0;

cv8_state.total_lines = 0;

cv8_state.symbols = saa_init(sizeof(struct cv8_symbol));
cv8_state.last_sym = NULL;
}

static struct source_file *register_file(const char *filename);
static struct coff_Section *find_section(int32_t segto);
static int find_section(int32_t segto);

static void cv8_linenum(const char *filename, int32_t linenumber,
int32_t segto)
{
struct coff_Section *s;
struct linepair *li;
struct source_file *file;
struct sect_lines *sl;
int i;

s = find_section(segto);
if (s == NULL)
i = find_section(segto);
if (i == -1)
return;

if ((s->flags & IMAGE_SCN_MEM_EXECUTE) == 0)
if ((coff_sects[i]->flags & IMAGE_SCN_MEM_EXECUTE) == 0)
return;

file = register_file(filename);
sl = &register_file(filename)->sects[i];

li = saa_wstruct(file->lines);
li->file_offset = cv8_state.text_offset;
if (!sl->lines)
sl->lines = saa_init(sizeof(struct linepair));

li = saa_wstruct(sl->lines);
li->file_offset = coff_sects[i]->len;
li->linenumber = linenumber;

file->num_lines++;
cv8_state.total_lines++;
sl->num_lines++;
}

static void cv8_deflabel(char *name, int32_t segment, int64_t offset,
int is_global, char *special)
{
struct cv8_symbol *sym;
struct coff_Section *s;
int i;

(void)special;

/* Skip macro-local labels */
if (!strncmp(name, "..@", 3))
if (name[0] == '.' && name[1] == '.' && name[2] == '@' && name[3] >= '0' && name[3] <= '9')
return;

s = find_section(segment);
if (s == NULL)
i = find_section(segment);
if (i == -1)
return;

/* MS linker errors on relocations to .pdata section, so skip such symbols */
if (!strcmp(s->name, ".pdata"))
if (!strcmp(coff_sects[i]->name, ".pdata"))
return;

sym = saa_wstruct(cv8_state.symbols);

if (s->flags & IMAGE_SCN_MEM_EXECUTE)
if (coff_sects[i]->flags & IMAGE_SCN_MEM_EXECUTE)
sym->type = is_global ? SYMTYPE_PROC : SYMTYPE_CODE;
else
sym->type = is_global ? SYMTYPE_GDATA : SYMTYPE_LDATA;
Expand Down Expand Up @@ -269,17 +267,6 @@ static void cv8_typevalue(int32_t type)
}
}

static void cv8_output(int type, void *param)
{
struct coff_DebugInfo *dinfo = param;

(void)type;

if (dinfo->section && dinfo->section->name &&
!strncmp(dinfo->section->name, ".text", 5))
cv8_state.text_offset += dinfo->size;
}

static void build_symbol_table(struct coff_Section *const sect);
static void build_type_table(struct coff_Section *const sect);

Expand All @@ -298,8 +285,12 @@ static void cv8_cleanup(void)
build_type_table(type_sect);

list_for_each_safe(file, ftmp, cv8_state.source_files) {
int i;
nasm_free(file->fullname);
saa_free(file->lines);
for (i = 0; i < coff_nsects; i++)
if (file->sects[i].lines)
saa_free(file->sects[i].lines);
nasm_free(file->sects);
nasm_free(file);
}
hash_free(&cv8_state.file_hash);
Expand Down Expand Up @@ -383,7 +374,7 @@ static struct source_file *register_file(const char *filename)
file->filename = filename;
file->fullname = fullpath;
file->fullnamelen = strlen(fullpath);
file->lines = saa_init(sizeof(struct linepair));
file->sects = nasm_calloc(coff_nsects, sizeof(*file->sects));
*cv8_state.source_files_tail = file;
cv8_state.source_files_tail = &file->next;
calc_md5(fullpath, file->md5sum);
Expand All @@ -398,22 +389,19 @@ static struct source_file *register_file(const char *filename)
return file;
}

static struct coff_Section *find_section(int32_t segto)
static int find_section(int32_t segto)
{
int i;

for (i = 0; i < coff_nsects; i++) {
struct coff_Section *sec;
for (i = 0; i < coff_nsects; i++)
if (segto == coff_sects[i]->index)
return i;

sec = coff_sects[i];
if (segto == sec->index)
return sec;
}
return NULL;
return -1;
}

static void register_reloc(struct coff_Section *const sect,
char *sym, uint32_t addr, uint16_t type)
int reloc_sect, char *sym, uint32_t addr, uint16_t type)
{
struct coff_Reloc *r;
struct coff_Section *sec;
Expand All @@ -428,14 +416,9 @@ static void register_reloc(struct coff_Section *const sect,
r->symbase = SECT_SYMBOLS;
r->type = type;

r->symbol = 0;
for (i = 0; i < (uint32_t)coff_nsects; i++) {
sec = coff_sects[i];
if (!strcmp(sym, sec->name)) {
return;
}
r->symbol += 2;
}
r->symbol = reloc_sect * 2;
if (reloc_sect < coff_nsects)
return;

saa_rewind(coff_syms);
for (i = 0; i < coff_nsyms; i++) {
Expand Down Expand Up @@ -539,52 +522,58 @@ static void write_linenumber_table(struct coff_Section *const sect)
const uint32_t line_field_len = 8;

int i;
uint32_t field_length = 0;
size_t field_base;
struct source_file *file;
struct coff_Section *s;

for (i = 0; i < coff_nsects; i++) {
if (!strncmp(coff_sects[i]->name, ".text", 5))
break;
}

if (i == coff_nsects)
return;
s = coff_sects[i];

field_length = 12;
field_length += (cv8_state.num_files * file_field_len);
field_length += (cv8_state.total_lines * line_field_len);

section_write32(sect, 0x000000F2);
section_write32(sect, field_length);

field_base = sect->len;
section_write32(sect, 0); /* SECREL, updated by relocation */
section_write16(sect, 0); /* SECTION, updated by relocation*/
section_write16(sect, 0); /* pad */
section_write32(sect, s->len);

register_reloc(sect, s->name, field_base,
win64 ? IMAGE_REL_AMD64_SECREL : IMAGE_REL_I386_SECREL);

register_reloc(sect, s->name, field_base + 4,
win64 ? IMAGE_REL_AMD64_SECTION : IMAGE_REL_I386_SECTION);

list_for_each(file, cv8_state.source_files) {
struct linepair *li;

/* source mapping */
section_write32(sect, file->sourcetbl_off);
section_write32(sect, file->num_lines);
section_write32(sect, file_field_len + (file->num_lines * line_field_len));

/* the pairs */
saa_rewind(file->lines);
while ((li = saa_rstruct(file->lines))) {
section_write32(sect, li->file_offset);
section_write32(sect, li->linenumber |= 0x80000000);
uint32_t field_length;
size_t field_base;
struct source_file *file;
struct coff_Section *s;
unsigned num_files = 0;
unsigned total_lines = 0;

list_for_each(file, cv8_state.source_files)
if (file->sects[i].num_lines) {
num_files++;
total_lines += file->sects[i].num_lines;
}
if (!total_lines)
continue;

s = coff_sects[i];

field_length = 12;
field_length += (num_files * file_field_len);
field_length += (total_lines * line_field_len);

section_write32(sect, 0x000000F2);
section_write32(sect, field_length);

field_base = sect->len;
section_write32(sect, 0); /* SECREL, updated by relocation */
section_write16(sect, 0); /* SECTION, updated by relocation*/
section_write16(sect, 0); /* pad */
section_write32(sect, s->len);

register_reloc(sect, i, NULL, field_base,
win64 ? IMAGE_REL_AMD64_SECREL : IMAGE_REL_I386_SECREL);

register_reloc(sect, i, NULL, field_base + 4,
win64 ? IMAGE_REL_AMD64_SECTION : IMAGE_REL_I386_SECTION);

list_for_each(file, cv8_state.source_files) {
struct linepair *li;

/* source mapping */
section_write32(sect, file->sourcetbl_off);
section_write32(sect, file->sects[i].num_lines);
section_write32(sect, file_field_len + (file->sects[i].num_lines * line_field_len));

/* the pairs */
saa_rewind(file->sects[i].lines);
while ((li = saa_rstruct(file->sects[i].lines))) {
section_write32(sect, li->file_offset);
section_write32(sect, li->linenumber |= 0x80000000);
}
}
}
}
Expand Down Expand Up @@ -693,10 +682,10 @@ static uint32_t write_symbolinfo_symbols(struct coff_Section *sect)

section_wbytes(sect, sym->name, strlen(sym->name) + 1);

register_reloc(sect, sym->name, field_base,
register_reloc(sect, coff_nsects, sym->name, field_base,
win64 ? IMAGE_REL_AMD64_SECREL :
IMAGE_REL_I386_SECREL);
register_reloc(sect, sym->name, field_base + 4,
register_reloc(sect, coff_nsects, sym->name, field_base + 4,
win64 ? IMAGE_REL_AMD64_SECTION :
IMAGE_REL_I386_SECTION);
}
Expand Down