📄 outelf.c
字号:
elf_section_header (0, 0, 0, NULL, FALSE, 0L, 0, 0, 0, 0); /* SHN_UNDEF */
scount=1; /* needed for the stabs debugging to track the symtable section */
p = shstrtab+1;
for (i=0; i<nsects; i++) {
elf_section_header (p - shstrtab, sects[i]->type, sects[i]->flags,
(sects[i]->type == SHT_PROGBITS ?
sects[i]->data : NULL), TRUE,
sects[i]->len, 0, 0, sects[i]->align, 0);
p += strlen(p)+1;
scount++; /* dito */
}
elf_section_header (p - shstrtab, 1, 0, comment, FALSE,
(long)commlen, 0, 0, 1, 0);/* .comment */
scount++; /* dito */
p += strlen(p)+1;
elf_section_header (p - shstrtab, 3, 0, shstrtab, FALSE,
(long)shstrtablen, 0, 0, 1, 0);/* .shstrtab */
scount++; /* dito */
p += strlen(p)+1;
elf_section_header (p - shstrtab, 2, 0, symtab, TRUE,
symtablen, nsects+4, symtablocal, 4, 16);/* .symtab */
symtabsection = scount; /* now we got the symtab section index in the ELF file */
p += strlen(p)+1;
elf_section_header (p - shstrtab, 3, 0, strs, TRUE,
strslen, 0, 0, 1, 0); /* .strtab */
for (i=0; i<nsects; i++) if (sects[i]->head) {
p += strlen(p)+1;
elf_section_header (p - shstrtab, 9, 0, sects[i]->rel, TRUE,
sects[i]->rellen, nsects+3, i+1, 4, 8);
}
if (of_elf.current_dfmt == &df_stabs) {
/* for debugging information, create the last three sections
which are the .stab , .stabstr and .rel.stab sections respectively */
/* this function call creates the stab sections in memory */
stabs_generate();
if ((stabbuf)&&(stabstrbuf)&&(stabrelbuf)) {
p += strlen(p)+1;
elf_section_header(p-shstrtab,1,0,stabbuf,0,stablen,nsections-2,0,4,12);
p += strlen(p)+1;
elf_section_header(p-shstrtab,3,0,stabstrbuf,0,stabstrlen,0,0,4,0);
p += strlen(p)+1;
/* link -> symtable info -> section to refer to */
elf_section_header(p-shstrtab,9,0,stabrelbuf,0,stabrellen,symtabsection,nsections-3,4,8);
}
}
fwrite (align_str, align, 1, elffp);
/*
* Now output the sections.
*/
elf_write_sections();
nasm_free (elf_sects);
saa_free (symtab);
}
static struct SAA *elf_build_symtab (long *len, long *local)
{
struct SAA *s = saa_init(1L);
struct Symbol *sym;
unsigned char entry[16], *p;
int i;
*len = *local = 0;
/*
* First, an all-zeros entry, required by the ELF spec.
*/
saa_wbytes (s, NULL, 16L); /* null symbol table entry */
*len += 16;
(*local)++;
/*
* Next, an entry for the file name.
*/
p = entry;
WRITELONG (p, 1); /* we know it's 1st thing in strtab */
WRITELONG (p, 0); /* no value */
WRITELONG (p, 0); /* no size either */
WRITESHORT (p, 4); /* type FILE */
WRITESHORT (p, SHN_ABS);
saa_wbytes (s, entry, 16L);
*len += 16;
(*local)++;
/*
* Now some standard symbols defining the segments, for relocation
* purposes.
*/
for (i = 1; i <= nsects+1; i++) {
p = entry;
WRITELONG (p, 0); /* no symbol name */
WRITELONG (p, 0); /* offset zero */
WRITELONG (p, 0); /* size zero */
WRITESHORT (p, 3); /* local section-type thing */
WRITESHORT (p, (i==1 ? SHN_ABS : i-1)); /* the section id */
saa_wbytes (s, entry, 16L);
*len += 16;
(*local)++;
}
/*
* Now the other local symbols.
*/
saa_rewind (syms);
while ( (sym = saa_rstruct (syms)) ) {
if (sym->type & SYM_GLOBAL)
continue;
p = entry;
WRITELONG (p, sym->strpos);
WRITELONG (p, sym->value);
WRITELONG (p, sym->size);
WRITESHORT (p, sym->type); /* local non-typed thing */
WRITESHORT (p, sym->section);
saa_wbytes (s, entry, 16L);
*len += 16;
(*local)++;
}
/*
* Now the global symbols.
*/
saa_rewind (syms);
while ( (sym = saa_rstruct (syms)) ) {
if (!(sym->type & SYM_GLOBAL))
continue;
p = entry;
WRITELONG (p, sym->strpos);
WRITELONG (p, sym->value);
WRITELONG (p, sym->size);
WRITESHORT (p, sym->type); /* global non-typed thing */
WRITESHORT (p, sym->section);
saa_wbytes (s, entry, 16L);
*len += 16;
}
return s;
}
static struct SAA *elf_build_reltab (long *len, struct Reloc *r) {
struct SAA *s;
unsigned char *p, entry[8];
if (!r)
return NULL;
s = saa_init(1L);
*len = 0;
while (r) {
long sym = r->symbol;
if (sym >= GLOBAL_TEMP_BASE)
sym += -GLOBAL_TEMP_BASE + (nsects+3) + nlocals;
p = entry;
WRITELONG (p, r->address);
WRITELONG (p, (sym << 8) + r->type);
saa_wbytes (s, entry, 8L);
*len += 8;
r = r->next;
}
return s;
}
static void elf_section_header (int name, int type, int flags,
void *data, int is_saa, long datalen,
int link, int info, int align, int eltsize)
{
elf_sects[elf_nsect].data = data;
elf_sects[elf_nsect].len = datalen;
elf_sects[elf_nsect].is_saa = is_saa;
elf_nsect++;
fwritelong ((long)name, elffp);
fwritelong ((long)type, elffp);
fwritelong ((long)flags, elffp);
fwritelong (0L, elffp); /* no address, ever, in object files */
fwritelong (type == 0 ? 0L : elf_foffs, elffp);
fwritelong (datalen, elffp);
if (data)
elf_foffs += (datalen+SEG_ALIGN_1) & ~SEG_ALIGN_1;
fwritelong ((long)link, elffp);
fwritelong ((long)info, elffp);
fwritelong ((long)align, elffp);
fwritelong ((long)eltsize, elffp);
}
static void elf_write_sections (void)
{
int i;
for (i = 0; i < elf_nsect; i++)
if (elf_sects[i].data) {
long len = elf_sects[i].len;
long reallen = (len+SEG_ALIGN_1) & ~SEG_ALIGN_1;
long align = reallen - len;
if (elf_sects[i].is_saa)
saa_fpwrite (elf_sects[i].data, elffp);
else
fwrite (elf_sects[i].data, len, 1, elffp);
fwrite (align_str, align, 1, elffp);
}
}
static void elf_sect_write (struct Section *sect,
const unsigned char *data, unsigned long len)
{
saa_wbytes (sect->data, data, len);
sect->len += len;
}
static long elf_segbase (long segment)
{
return segment;
}
static int elf_directive (char *directive, char *value, int pass)
{
return 0;
}
static void elf_filename (char *inname, char *outname, efunc error)
{
strcpy(elf_module, inname);
standard_extension (inname, outname, ".o", error);
}
static const char *elf_stdmac[] = {
"%define __SECT__ [section .text]",
"%macro __NASM_CDecl__ 1",
"%define $_%1 $%1",
"%endmacro",
NULL
};
static int elf_set_info(enum geninfo type, char **val)
{
return 0;
}
static struct dfmt df_stabs = {
"ELF32 (i386) stabs debug format for Linux",
"stabs",
stabs_init,
stabs_linenum,
stabs_deflabel,
stabs_directive,
stabs_typevalue,
stabs_output,
stabs_cleanup
};
struct dfmt *elf_debugs_arr[2]={&df_stabs,NULL};
struct ofmt of_elf = {
"ELF32 (i386) object files (e.g. Linux)",
"elf",
NULL,
elf_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
};
/* again, the stabs debugging stuff (code) */
void stabs_init(struct ofmt *of,void *id,FILE *fp,efunc error)
{
}
void stabs_linenum(const char *filename,long linenumber,long 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 stabs_deflabel(char *name,long segment,long offset,int is_global,char *special)
{
}
void stabs_directive(const char *directive,const char *params)
{
}
void stabs_typevalue(long type)
{
}
void stabs_output(int type,void *param)
{
struct symlininfo *s;
struct linelist *el;
if (type==TY_STABSSYMLIN) {
if (stabs_immcall) {
s=(struct symlininfo *)param;
if (strcmp( s->name,".text")) return; /* we are only interested in the text stuff */
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;
}
}
}
stabs_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 stabs_generate(void)
{
int i,numfiles,strsize,numstabs=0,currfile,mainfileindex;
unsigned char *sbuf,*ssbuf,*rbuf,*sptr,*rptr;
char **allfiles;
int *fileidx;
struct linelist *ptr;
ptr=stabslines;
allfiles = (char **)nasm_malloc(numlinestabs*sizeof(char *));
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 = (unsigned char *)nasm_malloc((numlinestabs*2+3)*sizeof(struct stabentry));
ssbuf = (unsigned char *)nasm_malloc(strsize);
rbuf = (unsigned char *)nasm_malloc(numlinestabs*8*(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;
/* 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));
ptr=stabslines;
numstabs = 0;
if ( ptr ) {
/* this is the stab for the main source file */
WRITE_STAB(sptr, fileidx[mainfileindex], N_SO, 0, 0, 0);
/* relocation stuff */
/* IS THIS SANE? WHAT DOES SECTION+3 MEAN HERE? */
WRITELONG(rptr, (sptr-sbuf)-4);
WRITELONG(rptr, ((ptr->info.section+3)<<8)|R_386_32);
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 stuff */
/* IS THIS SANE? WHAT DOES SECTION+3 MEAN HERE? */
WRITELONG(rptr, (sptr-sbuf)-4);
WRITELONG(rptr, ((ptr->info.section+3)<<8)|R_386_32);
}
WRITE_STAB(sptr,0,N_SLINE,0,ptr->line,ptr->info.offset);
numstabs++;
/* relocation stuff */
/* IS THIS SANE? WHAT DOES SECTION+3 MEAN HERE? */
WRITELONG(rptr, (sptr-sbuf)-4);
WRITELONG(rptr, ((ptr->info.section+3)<<8)|R_386_32);
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 stabs_cleanup() {
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);
}
#endif /* OF_ELF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -