⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 outelf.c

📁 一个免费的汇编语言编译器的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    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 + -