📄 outelf64.c
字号:
return 1;
}
return 0;
}
static void elf_filename(char *inname, char *outname, efunc error)
{
strcpy(elf_module, inname);
standard_extension(inname, outname, ".o", error);
}
extern macros_t elf_stdmac[];
static int elf_set_info(enum geninfo type, char **val)
{
(void)type;
(void)val;
return 0;
}
static struct dfmt df_dwarf = {
"ELF64 (X86_64) dwarf debug format for Linux",
"dwarf",
debug64_init,
dwarf64_linenum,
debug64_deflabel,
debug64_directive,
debug64_typevalue,
dwarf64_output,
dwarf64_cleanup
};
static struct dfmt df_stabs = {
"ELF64 (X86_64) stabs debug format for Linux",
"stabs",
debug64_init,
stabs64_linenum,
debug64_deflabel,
debug64_directive,
debug64_typevalue,
stabs64_output,
stabs64_cleanup
};
struct dfmt *elf64_debugs_arr[3] = { &df_stabs, &df_dwarf, NULL };
struct ofmt of_elf64 = {
"ELF64 (x86_64) object files (e.g. Linux)",
"elf64",
NULL,
elf64_debugs_arr,
&null_debug_form,
elf_stdmac,
elf_init,
elf_set_info,
elf_out,
elf_deflabel,
elf_section_names,
elf_segbase,
elf_directive,
elf_filename,
elf_cleanup
};
/* common debugging routines */
void debug64_init(struct ofmt *of, void *id, FILE * fp, efunc error)
{
(void)of;
(void)id;
(void)fp;
(void)error;
}
void debug64_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 debug64_directive(const char *directive, const char *params)
{
(void)directive;
(void)params;
}
void debug64_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;
}
}
/* 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_DEBUGSYMLIN) {
if (debug_immcall) {
s = (struct symlininfo *)param;
if (!(sects[s->section]->flags & SHF_EXECINSTR))
return; /* line info is only collected for executable sections */
numlinestabs++;
el = (struct linelist *)nasm_malloc(sizeof(struct linelist));
el->info.offset = s->offset;
el->info.section = s->section;
el->info.name = s->name;
el->line = currentline;
el->filename = stabs_filename;
el->next = 0;
if (stabslines) {
stabslines->last->next = el;
stabslines->last = el;
} else {
stabslines = el;
stabslines->last = el;
}
}
}
debug_immcall = 0;
}
#define WRITE_STAB(p,n_strx,n_type,n_other,n_desc,n_value) \
do {\
WRITELONG(p,n_strx); \
WRITECHAR(p,n_type); \
WRITECHAR(p,n_other); \
WRITESHORT(p,n_desc); \
WRITELONG(p,n_value); \
} while (0)
/* for creating the .stab , .stabstr and .rel.stab sections in memory */
void stabs64_generate(void)
{
int i, numfiles, strsize, numstabs = 0, currfile, mainfileindex;
uint8_t *sbuf, *ssbuf, *rbuf, *sptr, *rptr;
char **allfiles;
int *fileidx;
struct linelist *ptr;
ptr = stabslines;
allfiles = (char **)nasm_malloc(numlinestabs * sizeof(int8_t *));
for (i = 0; i < numlinestabs; i++)
allfiles[i] = 0;
numfiles = 0;
while (ptr) {
if (numfiles == 0) {
allfiles[0] = ptr->filename;
numfiles++;
} else {
for (i = 0; i < numfiles; i++) {
if (!strcmp(allfiles[i], ptr->filename))
break;
}
if (i >= numfiles) {
allfiles[i] = ptr->filename;
numfiles++;
}
}
ptr = ptr->next;
}
strsize = 1;
fileidx = (int *)nasm_malloc(numfiles * sizeof(int));
for (i = 0; i < numfiles; i++) {
fileidx[i] = strsize;
strsize += strlen(allfiles[i]) + 1;
}
mainfileindex = 0;
for (i = 0; i < numfiles; i++) {
if (!strcmp(allfiles[i], elf_module)) {
mainfileindex = i;
break;
}
}
/* worst case size of the stab buffer would be:
the sourcefiles changes each line, which would mean 1 SOL, 1 SYMLIN per line
*/
sbuf =
(uint8_t *)nasm_malloc((numlinestabs * 2 + 3) *
sizeof(struct stabentry));
ssbuf = (uint8_t *)nasm_malloc(strsize);
rbuf = (uint8_t *)nasm_malloc(numlinestabs * 16 * (2 + 3));
rptr = rbuf;
for (i = 0; i < numfiles; i++) {
strcpy((char *)ssbuf + fileidx[i], allfiles[i]);
}
ssbuf[0] = 0;
stabstrlen = strsize; /* set global variable for length of stab strings */
sptr = sbuf;
ptr = stabslines;
numstabs = 0;
if (ptr) {
/* this is the first stab, its strx points to the filename of the
the source-file, the n_desc field should be set to the number
of remaining stabs
*/
WRITE_STAB(sptr, fileidx[0], 0, 0, 0, strlen(allfiles[0] + 12));
/* this is the stab for the main source file */
WRITE_STAB(sptr, fileidx[mainfileindex], N_SO, 0, 0, 0);
/* relocation table entry */
/* Since the symbol table has two entries before */
/* the section symbols, the index in the info.section */
/* member must be adjusted by adding 2 */
WRITEDLONG(rptr, (int64_t)(sptr - sbuf) - 4);
WRITELONG(rptr, R_X86_64_32);
WRITELONG(rptr, ptr->info.section + 2);
numstabs++;
currfile = mainfileindex;
}
while (ptr) {
if (strcmp(allfiles[currfile], ptr->filename)) {
/* oops file has changed... */
for (i = 0; i < numfiles; i++)
if (!strcmp(allfiles[i], ptr->filename))
break;
currfile = i;
WRITE_STAB(sptr, fileidx[currfile], N_SOL, 0, 0,
ptr->info.offset);
numstabs++;
/* relocation table entry */
WRITEDLONG(rptr, (int64_t)(sptr - sbuf) - 4);
WRITELONG(rptr, R_X86_64_32);
WRITELONG(rptr, ptr->info.section + 2);
}
WRITE_STAB(sptr, 0, N_SLINE, 0, ptr->line, ptr->info.offset);
numstabs++;
/* relocation table entry */
WRITEDLONG(rptr, (int64_t)(sptr - sbuf) - 4);
WRITELONG(rptr, R_X86_64_32);
WRITELONG(rptr, ptr->info.section + 2);
ptr = ptr->next;
}
((struct stabentry *)sbuf)->n_desc = numstabs;
nasm_free(allfiles);
nasm_free(fileidx);
stablen = (sptr - sbuf);
stabrellen = (rptr - rbuf);
stabrelbuf = rbuf;
stabbuf = sbuf;
stabstrbuf = ssbuf;
}
void stabs64_cleanup(void)
{
struct linelist *ptr, *del;
if (!stabslines)
return;
ptr = stabslines;
while (ptr) {
del = ptr;
ptr = ptr->next;
nasm_free(del);
}
if (stabbuf)
nasm_free(stabbuf);
if (stabrelbuf)
nasm_free(stabrelbuf);
if (stabstrbuf)
nasm_free(stabstrbuf);
}
/* dwarf routines */
void dwarf64_linenum(const char *filename, int32_t linenumber, int32_t segto)
{
(void)segto;
dwarf64_findfile(filename);
debug_immcall = 1;
currentline = linenumber;
}
/* called from elf_out with type == TY_DEBUGSYMLIN */
void dwarf64_output(int type, void *param)
{
int ln, aa, inx, maxln, soc;
struct symlininfo *s;
struct SAA *plinep;
(void)type;
s = (struct symlininfo *)param;
/* line number info is only gathered for executable sections */
if (!(sects[s->section]->flags & SHF_EXECINSTR))
return;
/* Check if section index has changed */
if (!(dwarf_csect && (dwarf_csect->section) == (s->section)))
{
dwarf64_findsect(s->section);
}
/* do nothing unless line or file has changed *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -