summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Kukunas <james.t.kukunas@linux.intel.com>2016-05-16 16:15:44 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2016-05-17 11:35:44 -0700
commitf8259c662a8e84195db6d80081936d6c7cf5e17d (patch)
treed35e5801cd56d947ebb42e4bbe630642d8c8828e
parentc9fd7b2aa5086205a626f8312bbaa5043b72a6d7 (diff)
downloadnasm-f8259c662a8e84195db6d80081936d6c7cf5e17d.tar.gz
codeview.c: Add support for multiple source files
Handle the existence of multiple source files, as is normal when using include files. Signed-of-by: Jim Kukunas <james.t.kukunas@linux.intel.com> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--output/codeview.c154
1 files changed, 120 insertions, 34 deletions
diff --git a/output/codeview.c b/output/codeview.c
index 84abd7d8..d490fa4b 100644
--- a/output/codeview.c
+++ b/output/codeview.c
@@ -74,8 +74,20 @@ struct dfmt df_cv8 = {
/*******************************************************************************
* dfmt callbacks
******************************************************************************/
+struct source_file;
+
struct source_file {
char *name;
+ uint32_t namelen;
+
+ struct source_file *next;
+
+ uint32_t filetbl_off;
+ uint32_t sourcetbl_off;
+
+ struct SAA *lines;
+ uint32_t num_lines;
+
unsigned char md5sum[MD5_HASHBYTES];
};
@@ -125,9 +137,10 @@ struct cv8_state {
uint32_t text_offset;
struct source_file source_file;
+ unsigned num_files;
+ uint32_t total_filename_len;
- struct SAA *lines;
- uint32_t num_lines;
+ unsigned total_lines;
struct SAA *symbols;
struct cv8_symbol *last_sym;
@@ -151,8 +164,13 @@ static void cv8_init(void)
cv8_state.text_offset = 0;
- cv8_state.lines = saa_init(sizeof(struct linepair));
- cv8_state.num_lines = 0;
+ cv8_state.source_file.name = NULL;
+ cv8_state.source_file.next = NULL;
+
+ 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;
@@ -160,7 +178,7 @@ static void cv8_init(void)
cv8_state.cwd = nasm_realpath(".");
}
-static void register_file(const char *filename);
+static struct source_file *register_file(const char *filename);
static struct coff_Section *find_section(int32_t segto);
static void cv8_linenum(const char *filename, int32_t linenumber,
@@ -168,6 +186,7 @@ static void cv8_linenum(const char *filename, int32_t linenumber,
{
struct coff_Section *s;
struct linepair *li;
+ struct source_file *file;
s = find_section(segto);
if (s == NULL)
@@ -176,14 +195,14 @@ static void cv8_linenum(const char *filename, int32_t linenumber,
if ((s->flags & IMAGE_SCN_MEM_EXECUTE) == 0)
return;
- if (cv8_state.source_file.name == NULL)
- register_file(filename);
+ file = register_file(filename);
- li = saa_wstruct(cv8_state.lines);
+ li = saa_wstruct(file->lines);
li->file_offset = cv8_state.text_offset;
li->linenumber = linenumber;
- cv8_state.num_lines++;
+ file->num_lines++;
+ cv8_state.total_lines++;
}
static void cv8_deflabel(char *name, int32_t segment, int64_t offset,
@@ -277,6 +296,7 @@ static void build_type_table(struct coff_Section *const sect);
static void cv8_cleanup(void)
{
struct cv8_symbol *sym;
+ struct source_file *file;
struct coff_Section *symbol_sect = coff_sects[cv8_state.symbol_sect];
struct coff_Section *type_sect = coff_sects[cv8_state.type_sect];
@@ -284,8 +304,16 @@ static void cv8_cleanup(void)
build_symbol_table(symbol_sect);
build_type_table(type_sect);
- if (cv8_state.source_file.name != NULL)
+ if (cv8_state.source_file.name) {
nasm_free(cv8_state.source_file.name);
+ saa_free(cv8_state.source_file.lines);
+ }
+
+ list_for_each(file, cv8_state.source_file.next) {
+ nasm_free(file->name);
+ saa_free(file->lines);
+ free(file);
+ }
if (cv8_state.cwd != NULL)
nasm_free(cv8_state.cwd);
@@ -339,11 +367,40 @@ done:
return;
}
-static void register_file(const char *filename)
+static struct source_file *register_file(const char *filename)
{
- cv8_state.source_file.name = nasm_realpath(filename);
- memset(cv8_state.source_file.md5sum, 0, MD5_HASHBYTES);
- calc_md5(filename, cv8_state.source_file.md5sum);
+ struct source_file *file;
+
+ char *fullpath = nasm_realpath(filename);
+
+ for (file = &cv8_state.source_file; file != NULL; file = file->next) {
+ if (file->name != NULL && !strcmp(file->name, fullpath)) {
+ free(fullpath);
+ return file;
+ }
+ }
+
+ if (cv8_state.source_file.name == NULL) {
+ file = &cv8_state.source_file;
+ } else {
+ struct source_file *next;
+ file = nasm_malloc(sizeof(struct source_file));
+ for (next = &cv8_state.source_file; next->next != NULL; next = next->next) {}
+ next->next = file;
+ }
+
+ memset(file, 0, sizeof(struct source_file));
+
+ file->name = fullpath;
+ file->namelen = strlen(fullpath);
+ file->lines = saa_init(sizeof(struct linepair));
+ file->next = NULL;
+ calc_md5(fullpath, file->md5sum);
+
+ cv8_state.num_files++;
+ cv8_state.total_filename_len += file->namelen + 1;
+
+ return file;
}
static struct coff_Section *find_section(int32_t segto)
@@ -433,40 +490,63 @@ static inline void section_wbytes(struct coff_Section *sect, const void *buf,
static void write_filename_table(struct coff_Section *const sect)
{
- uint32_t field_length = 0;
- size_t filename_len = strlen(cv8_state.source_file.name);
+ uint32_t field_length;
+ uint32_t tbl_off = 1; /* offset starts at 1 to skip NULL entry */
+ struct source_file *file;
- field_length = 1 + filename_len + 1;
+ nasm_assert(cv8_state.source_file.name != NULL);
+ nasm_assert(cv8_state.num_files > 0);
+ nasm_assert(cv8_state.total_filename_len > 0);
+
+ field_length = 1 + cv8_state.total_filename_len;
section_write32(sect, 0x000000F3);
section_write32(sect, field_length);
section_write8(sect, 0);
- section_wbytes(sect, cv8_state.source_file.name, filename_len + 1);
+
+ for (file = &cv8_state.source_file; file != NULL; file = file->next) {
+ section_wbytes(sect, file->name, file->namelen + 1);
+ file->filetbl_off = tbl_off;
+ tbl_off += file->namelen + 1;
+ }
}
static void write_sourcefile_table(struct coff_Section *const sect)
{
+ const uint32_t entry_size = 4 + 2 + MD5_HASHBYTES + 2;
+
uint32_t field_length = 0;
+ uint32_t tbl_off = 0;
+ struct source_file *file;
- field_length = 4 + 2 + MD5_HASHBYTES + 2;
+ field_length = entry_size * cv8_state.num_files;
section_write32(sect, 0x000000F4);
section_write32(sect, field_length);
- section_write32(sect, 1); /* offset of filename in filename str table */
- section_write16(sect, 0x0110);
- section_wbytes(sect, cv8_state.source_file.md5sum, MD5_HASHBYTES);
- section_write16(sect, 0);
+ for (file = &cv8_state.source_file; file != NULL; file = file->next) {
+ nasm_assert(file->filetbl_off > 0);
+ section_write32(sect, file->filetbl_off);
+ section_write16(sect, 0x0110);
+ section_wbytes(sect, file->md5sum, MD5_HASHBYTES);
+ section_write16(sect, 0);
+
+ file->sourcetbl_off = tbl_off;
+ tbl_off += entry_size;
+ }
}
static void write_linenumber_table(struct coff_Section *const sect)
{
+ const uint32_t file_field_len = 12;
+ 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;
- struct linepair *li;
for (i = 0; i < coff_nsects; i++) {
if (!strncmp(coff_sects[i]->name, ".text", 5))
@@ -477,7 +557,9 @@ static void write_linenumber_table(struct coff_Section *const sect)
return;
s = coff_sects[i];
- field_length = 12 + 12 + (cv8_state.num_lines * 8);
+ 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);
@@ -494,16 +576,20 @@ static void write_linenumber_table(struct coff_Section *const sect)
register_reloc(sect, ".text", field_base + 4,
win64 ? IMAGE_REL_AMD64_SECTION : IMAGE_REL_I386_SECTION);
- /* 1 or more source mappings (we assume only 1) */
- section_write32(sect, 0);
- section_write32(sect, cv8_state.num_lines);
- section_write32(sect, 12 + (cv8_state.num_lines * 8));
+ for (file = &cv8_state.source_file; file != NULL; file = file->next) {
+ struct linepair *li;
- /* the pairs */
- saa_rewind(cv8_state.lines);
- while ((li = saa_rstruct(cv8_state.lines))) {
- section_write32(sect, li->file_offset);
- section_write32(sect, li->linenumber |= 0x80000000);
+ /* 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);
+ }
}
}