Dwarf support tweeks and clean-up

1. Add relocation entries for dwarf sections.
2. Combine common dwarf and stabs routines.
This commit is contained in:
Charles Crayne 2008-02-23 18:35:11 -08:00
parent 75ed1ebfb4
commit 986312b17a

View File

@ -1,4 +1,4 @@
/* outelf.c output routines for the Netwide Assembler to produce
/* outelf64.c output routines for the Netwide Assembler to produce
* ELF64 (x86_64 of course) object file format
*
* The Netwide Assembler is copyright (C) 1996 Simon Tatham and
@ -53,12 +53,15 @@
/* Definitions in lieu of dwarf.h */
#define DW_TAG_compile_unit 0x11
#define DW_TAG_subprogram 0x2e
#define DW_AT_low_pc 0x11
#define DW_AT_high_pc 0x12
#define DW_AT_frame_base 0x40
#define DW_AT_name 0x03
#define DW_AT_stmt_list 0x10
#define DW_AT_low_pc 0x11
#define DW_AT_high_pc 0x12
#define DW_AT_language 0x13
#define DW_AT_producer 0x25
#define DW_AT_frame_base 0x40
#define DW_FORM_addr 0x01
#define DW_FORM_data2 0x05
#define DW_FORM_data4 0x06
#define DW_FORM_string 0x08
#define DW_LNS_extended_op 0
@ -68,6 +71,8 @@
#define DW_LNE_end_sequence 1
#define DW_LNE_set_address 2
#define DW_LNE_define_file 3
#define DW_LANG_Mips_Assembler 0x8001
#define SOC(ln,aa) ln - line_base + (line_range * aa) + opcode_base
#if X86_MEMORY
@ -265,6 +270,8 @@ extern struct ofmt of_elf64;
#define SEG_ALIGN 16 /* alignment of sections in file */
#define SEG_ALIGN_1 (SEG_ALIGN-1)
#define TY_DEBUGSYMLIN 0x40 /* internal call to debug_out */
static const char align_str[SEG_ALIGN] = ""; /* ANSI will pad this with 0s */
static struct ELF_SECTDATA {
@ -272,7 +279,7 @@ static struct ELF_SECTDATA {
int64_t len;
bool is_saa;
} *elf_sects;
static int elf_nsect;
static int elf_nsect, nsections;
static int64_t elf_foffs;
static void elf_write(void);
@ -285,13 +292,12 @@ static struct SAA *elf_build_symtab(int32_t *, int32_t *);
static struct SAA *elf_build_reltab(uint64_t *, struct Reloc *);
static void add_sectname(char *, char *);
/* this stuff is needed for the stabs debugging format */
/* type values for stabs debugging sections */
#define N_SO 0x64 /* ID for main source file */
#define N_SOL 0x84 /* ID for sub-source file */
#define N_BINCL 0x82
#define N_EINCL 0xA2
#define N_BINCL 0x82 /* not currently used */
#define N_EINCL 0xA2 /* not currently used */
#define N_SLINE 0x44
#define TY_STABSSYMLIN 0x40 /* internal call to debug_out */
struct stabentry {
uint32_t n_strx;
@ -332,10 +338,10 @@ struct sectlist {
/* common debug variables */
static int currentline = 1;
static int debug_immcall = 0;
/* stabs debug variables */
static struct linelist *stabslines = 0;
static int stabs_immcall = 0;
static int numlinestabs = 0;
static char *stabs_filename = 0;
static int symtabsection;
@ -345,12 +351,13 @@ static int stablen, stabstrlen, stabrellen;
/* dwarf debug variables */
static struct linelist *dwarf_flist = 0, *dwarf_clist = 0, *dwarf_elist = 0;
static struct sectlist *dwarf_fsect = 0, *dwarf_csect = 0, *dwarf_esect = 0;
static int dwarf_immcall = 0, dwarf_numfiles = 0, dwarf_nsections;
static int dwarf_numfiles = 0, dwarf_nsections;
static uint8_t *arangesbuf = 0, *arangesrelbuf = 0, *pubnamesbuf = 0, *infobuf = 0, *inforelbuf = 0,
*abbrevbuf = 0, *linebuf = 0, *linerelbuf = 0, *framebuf = 0, *locbuf = 0;
static int8_t line_base = -5, line_range = 14, opcode_base = 13;
static int arangeslen, arangesrellen, pubnameslen, infolen, inforellen,
abbrevlen, linelen, linerellen, framelen, loclen;
static int64_t dwarf_infosym, dwarf_abbrevsym, dwarf_linesym;
static char workbuf[1024];
@ -358,21 +365,20 @@ static struct dfmt df_dwarf;
static struct dfmt df_stabs;
static struct Symbol *lastsym;
void stabs64_init(struct ofmt *, void *, FILE *, efunc);
/* common debugging routines */
void debug64_typevalue(int32_t);
void debug64_init(struct ofmt *, void *, FILE *, efunc);
void debug64_deflabel(char *, int32_t, int64_t, int, char *);
void debug64_directive(const char *, const char *);
/* stabs debugging routines */
void stabs64_linenum(const char *filename, int32_t linenumber, int32_t);
void stabs64_deflabel(char *, int32_t, int64_t, int, char *);
void stabs64_directive(const char *, const char *);
void stabs64_typevalue(int32_t);
void stabs64_output(int, void *);
void stabs64_generate(void);
void stabs64_cleanup(void);
/* dwarf debugging routines */
void dwarf64_init(struct ofmt *, void *, FILE *, efunc);
void dwarf64_linenum(const char *filename, int32_t linenumber, int32_t);
void dwarf64_deflabel(char *, int32_t, int64_t, int, char *);
void dwarf64_directive(const char *, const char *);
void dwarf64_typevalue(int32_t);
void dwarf64_output(int, void *);
void dwarf64_generate(void);
void dwarf64_cleanup(void);
@ -983,14 +989,13 @@ static void elf_out(int32_t segto, const void *data,
i = nsects - 1;
}
}
/* invoke current debug_output routine */
if (of_elf64.current_dfmt) {
sinfo.offset = s->len;
sinfo.section = i;
sinfo.segto = segto;
sinfo.name = s->name;
of_elf64.current_dfmt->debug_output(TY_STABSSYMLIN, &sinfo);
of_elf64.current_dfmt->debug_output(TY_DEBUGSYMLIN, &sinfo);
}
/* end of debugging stuff */
@ -1140,7 +1145,7 @@ static void elf_out(int32_t segto, const void *data,
static void elf_write(void)
{
int nsections, align;
int align;
int scount;
char *p;
int commlen;
@ -1186,9 +1191,10 @@ static void elf_write(void)
/* the dwarf debug standard specifies the following ten sections,
not all of which are currently implemented,
although all of them are defined. */
#define debug_aranges nsections-10
#define debug_info nsections-7
#define debug_line nsections-4
#define debug_aranges (int64_t) (nsections-10)
#define debug_info (int64_t) (nsections-7)
#define debug_abbrev (int64_t) (nsections-5)
#define debug_line (int64_t) (nsections-4)
add_sectname("", ".debug_aranges");
add_sectname(".rela", ".debug_aranges");
add_sectname("", ".debug_pubnames");
@ -1393,6 +1399,7 @@ static struct SAA *elf_build_symtab(int32_t *len, int32_t *local)
(*local)++;
}
/*
* Now the other local symbols.
*/
@ -1401,16 +1408,52 @@ static struct SAA *elf_build_symtab(int32_t *len, int32_t *local)
if (sym->type & SYM_GLOBAL)
continue;
p = entry;
WRITELONG(p, sym->strpos);
WRITELONG(p, sym->strpos); /* index into symbol string table */
WRITECHAR(p, sym->type); /* type and binding */
WRITECHAR(p, sym->other); /* visibility */
WRITESHORT(p, sym->section);
WRITEDLONG(p, (int64_t)sym->value);
WRITEDLONG(p, (int64_t)sym->size);
WRITESHORT(p, sym->section); /* index into section header table */
WRITEDLONG(p, (int64_t)sym->value); /* value of symbol */
WRITEDLONG(p, (int64_t)sym->size); /* size of symbol */
saa_wbytes(s, entry, 24L);
*len += 24;
(*local)++;
}
/*
* dwarf needs symbols for debug sections
* which are relocation targets.
*/
if (of_elf64.current_dfmt == &df_dwarf) {
dwarf_infosym = *local;
p = entry;
WRITELONG(p, 0); /* no symbol name */
WRITESHORT(p, STT_SECTION); /* type, binding, and visibility */
WRITESHORT(p, debug_info); /* section id */
WRITEDLONG(p, (uint64_t) 0); /* offset zero */
WRITEDLONG(p, (uint64_t) 0); /* size zero */
saa_wbytes(s, entry, 24L);
*len += 24;
(*local)++;
dwarf_abbrevsym = *local;
p = entry;
WRITELONG(p, 0); /* no symbol name */
WRITESHORT(p, STT_SECTION); /* type, binding, and visibility */
WRITESHORT(p, debug_abbrev); /* section id */
WRITEDLONG(p, (uint64_t) 0); /* offset zero */
WRITEDLONG(p, (uint64_t) 0); /* size zero */
saa_wbytes(s, entry, 24L);
*len += 24;
(*local)++;
dwarf_linesym = *local;
p = entry;
WRITELONG(p, 0); /* no symbol name */
WRITESHORT(p, STT_SECTION); /* type, binding, and visibility */
WRITESHORT(p, debug_line); /* section id */
WRITEDLONG(p, (uint64_t) 0); /* offset zero */
WRITEDLONG(p, (uint64_t) 0); /* size zero */
saa_wbytes(s, entry, 24L);
*len += 24;
(*local)++;
}
/*
* Now the global symbols.
@ -1448,8 +1491,11 @@ static struct SAA *elf_build_reltab(uint64_t *len, struct Reloc *r)
int64_t sym = r->symbol;
if (sym >= GLOBAL_TEMP_BASE)
sym += -GLOBAL_TEMP_BASE + (nsects + 2) + nlocals;
{
if (of_elf64.current_dfmt == &df_dwarf)
sym += -GLOBAL_TEMP_BASE + (nsects + 5) + nlocals;
else sym += -GLOBAL_TEMP_BASE + (nsects + 2) + nlocals;
}
p = entry;
WRITEDLONG(p, r->address);
WRITEDLONG(p, (sym << 32) + r->type);
@ -1577,22 +1623,22 @@ static int elf_set_info(enum geninfo type, char **val)
static struct dfmt df_dwarf = {
"ELF64 (X86_64) dwarf debug format for Linux",
"dwarf",
dwarf64_init,
debug64_init,
dwarf64_linenum,
dwarf64_deflabel,
dwarf64_directive,
dwarf64_typevalue,
debug64_deflabel,
debug64_directive,
debug64_typevalue,
dwarf64_output,
dwarf64_cleanup
};
static struct dfmt df_stabs = {
"ELF64 (X86_64) stabs debug format for Linux",
"stabs",
stabs64_init,
debug64_init,
stabs64_linenum,
stabs64_deflabel,
stabs64_directive,
stabs64_typevalue,
debug64_deflabel,
debug64_directive,
debug64_typevalue,
stabs64_output,
stabs64_cleanup
};
@ -1617,39 +1663,15 @@ struct ofmt of_elf64 = {
elf_cleanup
};
/* again, the stabs debugging stuff (code) */
void stabs64_init(struct ofmt *of, void *id, FILE * fp, efunc error)
/* common debugging routines */
void debug64_init(struct ofmt *of, void *id, FILE * fp, efunc error)
{
(void)of;
(void)id;
(void)fp;
(void)error;
}
void stabs64_linenum(const char *filename, int32_t linenumber, int32_t segto)
{
(void)segto;
if (!stabs_filename) {
stabs_filename = (char *)nasm_malloc(strlen(filename) + 1);
strcpy(stabs_filename, filename);
} else {
if (strcmp(stabs_filename, filename)) {
/* yep, a memory leak...this program is one-shot anyway, so who cares...
in fact, this leak comes in quite handy to maintain a list of files
encountered so far in the symbol lines... */
/* why not nasm_free(stabs_filename); we're done with the old one */
stabs_filename = (char *)nasm_malloc(strlen(filename) + 1);
strcpy(stabs_filename, filename);
}
}
stabs_immcall = 1;
currentline = linenumber;
}
void stabs64_deflabel(char *name, int32_t segment, int64_t offset, int is_global,
void debug64_deflabel(char *name, int32_t segment, int64_t offset, int is_global,
char *special)
{
(void)name;
@ -1659,13 +1681,13 @@ void stabs64_deflabel(char *name, int32_t segment, int64_t offset, int is_global
(void)special;
}
void stabs64_directive(const char *directive, const char *params)
void debug64_directive(const char *directive, const char *params)
{
(void)directive;
(void)params;
}
void stabs64_typevalue(int32_t type)
void debug64_typevalue(int32_t type)
{
int32_t stype, ssize;
switch (TYM_TYPE(type)) {
@ -1728,12 +1750,38 @@ void stabs64_typevalue(int32_t type)
}
}
/* stabs debugging routines */
void stabs64_linenum(const char *filename, int32_t linenumber, int32_t segto)
{
(void)segto;
if (!stabs_filename) {
stabs_filename = (char *)nasm_malloc(strlen(filename) + 1);
strcpy(stabs_filename, filename);
} else {
if (strcmp(stabs_filename, filename)) {
/* yep, a memory leak...this program is one-shot anyway, so who cares...
in fact, this leak comes in quite handy to maintain a list of files
encountered so far in the symbol lines... */
/* why not nasm_free(stabs_filename); we're done with the old one */
stabs_filename = (char *)nasm_malloc(strlen(filename) + 1);
strcpy(stabs_filename, filename);
}
}
debug_immcall = 1;
currentline = linenumber;
}
void stabs64_output(int type, void *param)
{
struct symlininfo *s;
struct linelist *el;
if (type == TY_STABSSYMLIN) {
if (stabs_immcall) {
if (type == TY_DEBUGSYMLIN) {
if (debug_immcall) {
s = (struct symlininfo *)param;
if (!(sects[s->section]->flags & SHF_EXECINSTR))
return; /* line info is only collected for executable sections */
@ -1754,7 +1802,7 @@ void stabs64_output(int type, void *param)
}
}
}
stabs_immcall = 0;
debug_immcall = 0;
}
#define WRITE_STAB(p,n_strx,n_type,n_other,n_desc,n_value) \
@ -1923,101 +1971,16 @@ void stabs64_cleanup(void)
}
/* dwarf routines */
void dwarf64_init(struct ofmt *of, void *id, FILE * fp, efunc error)
{
(void)of;
(void)id;
(void)fp;
(void)error;
}
void dwarf64_linenum(const char *filename, int32_t linenumber, int32_t segto)
{
(void)segto;
dwarf64_findfile(filename);
dwarf_immcall = 1;
debug_immcall = 1;
currentline = linenumber;
}
void dwarf64_deflabel(char *name, int32_t segment, int64_t offset, int is_global,
char *special)
{
(void)name;
(void)segment;
(void)offset;
(void)is_global;
(void)special;
}
void dwarf64_directive(const char *directive, const char *params)
{
(void)directive;
(void)params;
}
void dwarf64_typevalue(int32_t type)
{
int32_t stype, ssize;
switch (TYM_TYPE(type)) {
case TY_LABEL:
ssize = 0;
stype = STT_NOTYPE;
break;
case TY_BYTE:
ssize = 1;
stype = STT_OBJECT;
break;
case TY_WORD:
ssize = 2;
stype = STT_OBJECT;
break;
case TY_DWORD:
ssize = 4;
stype = STT_OBJECT;
break;
case TY_FLOAT:
ssize = 4;
stype = STT_OBJECT;
break;
case TY_QWORD:
ssize = 8;
stype = STT_OBJECT;
break;
case TY_TBYTE:
ssize = 10;
stype = STT_OBJECT;
break;
case TY_OWORD:
ssize = 16;
stype = STT_OBJECT;
break;
case TY_COMMON:
ssize = 0;
stype = STT_COMMON;
break;
case TY_SEG:
ssize = 0;
stype = STT_SECTION;
break;
case TY_EXTERN:
ssize = 0;
stype = STT_NOTYPE;
break;
case TY_EQU:
ssize = 0;
stype = STT_NOTYPE;
break;
default:
ssize = 0;
stype = STT_NOTYPE;
break;
}
if (stype == STT_OBJECT && lastsym && !lastsym->type) {
lastsym->size = ssize;
lastsym->type = stype;
}
}
/* called from elf_out with type == TY_STABSSYMLIN */
/* called from elf_out with type == TY_DEBUGSYMLIN */
void dwarf64_output(int type, void *param)
{
int ln, aa, inx, maxln, soc;
@ -2036,7 +1999,7 @@ void dwarf64_output(int type, void *param)
dwarf64_findsect(s->section);
}
/* do nothing unless line or file has changed */
if (dwarf_immcall)
if (debug_immcall)
{
ln = currentline - dwarf_csect->line;
aa = s->offset - dwarf_csect->offset;
@ -2076,7 +2039,7 @@ void dwarf64_output(int type, void *param)
dwarf_csect->offset = s->offset;
}
/* show change handled */
dwarf_immcall = 0;
debug_immcall = 0;
}
}
@ -2087,7 +2050,7 @@ void dwarf64_generate(void)
int indx;
struct linelist *ftentry;
struct SAA *paranges, *ppubnames, *pinfo, *pabbrev, *plines, *plinep;
struct SAA *parangesrel, *plinesrel;
struct SAA *parangesrel, *plinesrel, *pinforel;
struct sectlist *psect;
size_t saalen, linepoff, totlen, highaddr;
@ -2096,6 +2059,9 @@ void dwarf64_generate(void)
paranges = saa_init(1L);
parangesrel = saa_init(1L);
WSAASHORT(paranges,workbuf,3); /* dwarf version */
WSAADLONG(parangesrel,workbuf, paranges->datalen+4);
WSAADLONG(parangesrel,workbuf, (dwarf_infosym << 32) + R_X86_64_32); /* reloc to info */
WSAADLONG(parangesrel,workbuf, (uint64_t) 0);
WSAALONG(paranges,workbuf,0); /* offset into info */
WSAACHAR(paranges,workbuf,8); /* pointer size */
WSAACHAR(paranges,workbuf,0); /* not segmented */
@ -2131,13 +2097,13 @@ void dwarf64_generate(void)
arangeslen = saalen + 4;
arangesbuf = pbuf = nasm_malloc(arangeslen);
WRITELONG(pbuf,saalen); /* initial length */
memcpy(pbuf, saa_rbytes(paranges, &saalen), saalen);
saa_rnbytes(paranges, pbuf, saalen);
saa_free(paranges);
/* build rela.aranges section */
arangesrellen = saalen = parangesrel->datalen;
arangesrelbuf = pbuf = nasm_malloc(arangesrellen);
memcpy(pbuf, saa_rbytes(parangesrel, &saalen), saalen);
saa_rnbytes(parangesrel, pbuf, saalen);
saa_free(parangesrel);
/* build pubnames section */
@ -2150,21 +2116,40 @@ void dwarf64_generate(void)
pubnameslen = saalen + 4;
pubnamesbuf = pbuf = nasm_malloc(pubnameslen);
WRITELONG(pbuf,saalen); /* initial length */
memcpy(pbuf, saa_rbytes(ppubnames, &saalen), saalen);
saa_rnbytes(ppubnames, pbuf, saalen);
saa_free(ppubnames);
/* build info section */
pinfo = saa_init(1L);
pinforel = saa_init(1L);
WSAASHORT(pinfo,workbuf,3); /* dwarf version */
WSAADLONG(pinforel,workbuf, pinfo->datalen + 4);
WSAADLONG(pinforel,workbuf, (dwarf_abbrevsym << 32) + R_X86_64_32); /* reloc to abbrev */
WSAADLONG(pinforel,workbuf, (uint64_t) 0);
WSAALONG(pinfo,workbuf,0); /* offset into abbrev */
WSAACHAR(pinfo,workbuf,8); /* pointer size */
WSAACHAR(pinfo,workbuf,1); /* abbrviation number LEB128u */
WSAADLONG(pinforel,workbuf, pinfo->datalen + 4);
WSAADLONG(pinforel,workbuf, (2LL << 32) + R_X86_64_64);
WSAADLONG(pinforel,workbuf, (uint64_t) 0);
WSAADLONG(pinfo,workbuf,0); /* DW_AT_low_pc */
WSAADLONG(pinforel,workbuf, pinfo->datalen + 4);
WSAADLONG(pinforel,workbuf, (2LL << 32) + R_X86_64_64);
WSAADLONG(pinforel,workbuf, (uint64_t) 0);
WSAADLONG(pinfo,workbuf,highaddr); /* DW_AT_high_pc */
WSAADLONG(pinforel,workbuf, pinfo->datalen + 4);
WSAADLONG(pinforel,workbuf, (dwarf_linesym << 32) + R_X86_64_32); /* reloc to line */
WSAADLONG(pinforel,workbuf, (uint64_t) 0);
WSAALONG(pinfo,workbuf,0); /* DW_AT_stmt_list */
strcpy(workbuf,elf_module); /* input file name */
saa_wbytes(pinfo, workbuf, (int32_t)(strlen(elf_module) + 1));
sprintf(workbuf, "NASM %s", NASM_VER);
saa_wbytes(pinfo, workbuf, (int32_t)(strlen(workbuf) + 1));
WSAASHORT(pinfo,workbuf,DW_LANG_Mips_Assembler);
WSAACHAR(pinfo,workbuf,2); /* abbrviation number LEB128u */
WSAADLONG(pinforel,workbuf, pinfo->datalen + 4);
WSAADLONG(pinforel,workbuf, (2LL << 32) + R_X86_64_64);
WSAADLONG(pinforel,workbuf, (uint64_t) 0);
WSAADLONG(pinfo,workbuf,0); /* DW_AT_low_pc */
WSAADLONG(pinfo,workbuf,0); /* DW_AT_frame_base */
WSAACHAR(pinfo,workbuf,0); /* end of entries */
@ -2172,18 +2157,14 @@ void dwarf64_generate(void)
infolen = saalen + 4;
infobuf = pbuf = nasm_malloc(infolen);
WRITELONG(pbuf,saalen); /* initial length */
memcpy(pbuf, saa_rbytes(pinfo, &saalen), saalen);
saa_rnbytes(pinfo, pbuf, saalen);
saa_free(pinfo);
/* build rela.info section */
inforellen = 48;
inforelbuf = pbuf = nasm_malloc(inforellen);
WRITEDLONG(pbuf, 12);
WRITEDLONG(pbuf, (2LL << 32) + R_X86_64_64);
WRITEDLONG(pbuf, (uint64_t) 0);
WRITEDLONG(pbuf, 20);
WRITEDLONG(pbuf, (2LL << 32) + R_X86_64_64);
WRITEDLONG(pbuf, (uint64_t) 0);
inforellen = saalen = pinforel->datalen;
inforelbuf = pbuf = nasm_malloc(inforellen);
saa_rnbytes(pinforel, pbuf, saalen);
saa_free(pinforel);
/* build abbrev section */
pabbrev = saa_init(1L);
@ -2199,6 +2180,10 @@ void dwarf64_generate(void)
WSAACHAR(pabbrev,workbuf,DW_FORM_data4);
WSAACHAR(pabbrev,workbuf,DW_AT_name);
WSAACHAR(pabbrev,workbuf,DW_FORM_string);
WSAACHAR(pabbrev,workbuf,DW_AT_producer);
WSAACHAR(pabbrev,workbuf,DW_FORM_string);
WSAACHAR(pabbrev,workbuf,DW_AT_language);
WSAACHAR(pabbrev,workbuf,DW_FORM_data2);
WSAASHORT(pabbrev,workbuf,0); /* end of entry */
/* LEB128u usage same as above */
WSAACHAR(pabbrev,workbuf,2); /* entry number */
@ -2211,7 +2196,7 @@ void dwarf64_generate(void)
WSAASHORT(pabbrev,workbuf,0); /* end of entry */
abbrevlen = saalen = pabbrev->datalen;
abbrevbuf = pbuf = nasm_malloc(saalen);
memcpy(pbuf, saa_rbytes(pabbrev, &saalen), saalen);
saa_rnbytes(pabbrev, pbuf, saalen);
saa_free(pabbrev);
/* build line section */
@ -2256,7 +2241,7 @@ void dwarf64_generate(void)
WRITELONG(pbuf,linepoff); /* offset to line number program */
/* write line header */
saalen = linepoff;
memcpy(pbuf, saa_rbytes(plines, &saalen), saalen);
saa_rnbytes(plines, pbuf, saalen); /* read a given no. of bytes */
pbuf += linepoff;
saa_free(plines);
/* concatonate line program ranges */
@ -2270,7 +2255,7 @@ void dwarf64_generate(void)
WSAADLONG(plinesrel,workbuf, (uint64_t) 0);
plinep = psect->psaa;
saalen = plinep->datalen;
memcpy(pbuf, saa_rbytes(plinep, &saalen), saalen);
saa_rnbytes(plinep, pbuf, saalen);
pbuf += saalen;
linepoff += saalen;
saa_free(plinep);
@ -2282,7 +2267,7 @@ void dwarf64_generate(void)
/* build rela.lines section */
linerellen =saalen = plinesrel->datalen;
linerelbuf = pbuf = nasm_malloc(linerellen);
memcpy(pbuf, saa_rbytes(plinesrel, &saalen), saalen);
saa_rnbytes(plinesrel, pbuf, saalen);
saa_free(plinesrel);
/* build frame section */