Esempio n. 1
0
static void writeexec(struct GlobalVars *gv,FILE *f)
/* creates a TOS executable file (which is relocatable) */
{
  struct LinkedSection *sections[3];
  int nsyms = tos_initwrite(gv,sections);
  int i;

  tos_header(f,sections[0] ? sections[0]->size+sections[0]->gapsize : 0,
             sections[1] ? sections[1]->size+sections[1]->gapsize : 0,
             sections[2] ? sections[2]->size : 0,
             (unsigned long)nsyms*sizeof(struct DRIsym),gv->tosflags);

  for (i=0; i<3; i++)
    calc_relocs(gv,sections[i]);

  if (sections[0]) {
    fwritex(f,sections[0]->data,sections[0]->filesize);
    fwritegap(f,(sections[0]->size-sections[0]->filesize)+sections[0]->gapsize);
  }

  if (sections[1]) {
    fwritex(f,sections[1]->data,sections[1]->filesize);
    fwritegap(f,(sections[1]->size-sections[1]->filesize)+sections[1]->gapsize);
  }

  if (nsyms)
    tos_symboltable(gv,f,sections);

  tos_writerelocs(gv,f,sections);
}
Esempio n. 2
0
File: t_rawseg.c Progetto: 8l/vlink
static void rawseg_writeexec(struct GlobalVars *gv,FILE *f)
/* creates a new file for each segment, writes file name, start address */
/* and length into the output file */
{
  const char *fn = "rawseg_writeexec(): ";
  bool firstsec;
  unsigned long addr;
  FILE *segf;
  struct Phdr *p;
  struct LinkedSection *ls,*prevls;
  struct SegReloc *srlist;
  char buf[256];

  for (p=gv->phdrlist; p; p=p->next) {
    if (p->type==PT_LOAD && (p->flags&PHDR_USED) &&
        p->start!=ADDR_NONE && p->start_vma!=ADDR_NONE) {

      firstsec = TRUE;
      srlist = NULL;
      snprintf(buf,256,"%s.%s",gv->dest_name,p->name);
      segf = fopen(buf,"wb");
      if (segf == NULL) {
        error(29,buf);  /* cannot create file */
        continue;
      }

      /* write file name, start address and length of segment to output */
      fprintf(f,"\"%s\" 0x%llx 0x%llx\n",buf,p->start,p->mem_end-p->start);

      /* write segment's sections */
      for (ls=(struct LinkedSection *)gv->lnksec.first;
           ls->n.next!=NULL; ls=(struct LinkedSection *)ls->n.next) {
        if (ls->copybase>=(unsigned long)p->start &&
            (ls->copybase+ls->size)<=(unsigned long)p->mem_end &&
            (ls->flags & SF_ALLOC)) {

          if (gv->keep_relocs) {
            /* remember relocations, adjusted from section to segment base */
            struct Reloc *r;
            struct RelocInsert *ri;
            struct LinkedSection *relsec;
            struct Phdr *relph;

            for (r=(struct Reloc *)ls->relocs.first;
                 r->n.next!=NULL; r=(struct Reloc *)r->n.next) {
              if (ri = r->insert) {
                if (r->rtype!=R_ABS || ri->bpos!=0 || ri->bsiz!=32) {
                  /* only absolute 32-bit relocs are supported */
                  error(32,fff_rawseg.tname,reloc_name[r->rtype],
                        (int)ri->bpos,(int)ri->bsiz,ri->mask,
                        ls->name,r->offset);
                  continue;
                }
              }
              else
                continue;

              if (r->relocsect.lnk == NULL) {
                if (r->flags & RELF_DYNLINK)
                  continue;  /* NULL, because it was resolved by a sh.obj. */
                else
                  ierror("%sReloc type %d (%s) at %s+0x%lx "
                         "(addend 0x%llx) is missing a relocsect.lnk",
                         fn,(int)r->rtype,reloc_name[r->rtype],ls->name,
                         r->offset,r->addend);
              }
              relsec = r->relocsect.lnk;

              /* find out to which segment relsec belongs */
              for (relph=gv->phdrlist; relph; relph=relph->next) {
                if (relph->type==PT_LOAD && (relph->flags&PHDR_USED) &&
                    relph->start!=ADDR_NONE && relph->start_vma!=ADDR_NONE) {
                  if (relsec->copybase>=(unsigned long)relph->start &&
                      (relsec->copybase+relsec->size)<=
                      (unsigned long)relph->mem_end &&
                      (relsec->flags & SF_ALLOC))
                    break;
                }
              }
              /* use segment's base address for relocation instead */
              if (relph) {
                lword segoffs,a,v;
                struct SegReloc *newsr,*srp;

                segoffs = (lword)relsec->copybase - relph->start;
                v = writesection(gv,ls->data+r->offset,r,r->addend+segoffs);
                if (v != 0) {
                  /* Calculated value doesn't fit into relocation type x ... */
                  if (ri = r->insert)
                    error(35,gv->dest_name,ls->name,r->offset,v,
                          reloc_name[r->rtype],(int)ri->bpos,
                          (int)ri->bsiz,ri->mask);
                  else
                    ierror("%sReloc (%s+%lx), type=%s, without RelocInsert",
                           fn,ls->name,r->offset,reloc_name[r->rtype]);
                }

                /* remember relocation offset and segment for later */
                newsr = alloc(sizeof(struct SegReloc));
                newsr->next = NULL;
                newsr->seg = relph;
                newsr->offset = (ls->copybase - (unsigned long)p->start) +
                                r->offset;
                if (srp = srlist) {
                  while (srp->next)
                    srp = srp->next;
                  srp->next = newsr;
                }
                else
                  srlist = newsr;
              }
              else
                ierror("%sNo segment for reloc offset section '%s'",
                       fn,relsec->name);
            }
          }
          else
            calc_relocs(gv,ls);

          if (!firstsec) {
            /* write an alignment gap, when needed */
            if (ls->copybase > addr)
              fwritegap(segf,ls->copybase-addr);
            else if (ls->copybase < addr)
              error(98,fff[gv->dest_format]->tname,ls->name,prevls->name);
          }
          else
            firstsec = FALSE;

          fwritex(segf,ls->data,ls->size);

          addr = ls->copybase + ls->size;
          prevls = ls;
        }
      }
      fclose(segf);

      if (srlist) {
        /* write relocation files for this segment */
        struct Phdr *relph;
        struct SegReloc *sr;
        uint32_t rcnt;
        FILE *rf;

        for (relph=gv->phdrlist; relph; relph=relph->next) {
          for (sr=srlist,rf=NULL,rcnt=0; sr; sr=sr->next) {
            if (sr->seg == relph) {
              if (!rf) {
                snprintf(buf,256,"%s.%s.rel%s",
                         gv->dest_name,p->name,relph->name);
                rf = fopen(buf,"wb");
                if (rf == NULL) {
                  error(29,buf);  /* cannot create file */
                  continue;
                }
                fwritegap(rf,4);  /* number of relocs will be stored here */
              }
              if (gv->endianess == _BIG_ENDIAN_)
                fwrite32be(rf,sr->offset);
              else
                fwrite32le(rf,sr->offset);
              rcnt++;
            }
          }
          if (rf) {
            /* write number of relocs into the first word */
            fseek(rf,0,SEEK_SET);
            if (gv->endianess == _BIG_ENDIAN_)
              fwrite32be(rf,rcnt);
            else
              fwrite32le(rf,rcnt);
            fclose(rf);
          }
        }
      }
    }
  }
}
Esempio n. 3
0
static void aoutmint_writeexec(struct GlobalVars *gv,FILE *f)
/* creates an a.out-MiNT executable file */
{
    const int be = _BIG_ENDIAN_;
    uint8_t jmp_entry_code[] = { 0x20,0x3a,0x00,0x1a,0x4e,0xfb,0x08,0xfa };
    struct LinkedSection *sections[3];
    unsigned long secsizes[2];
    struct mint_exec me;
    long tparel_offset,tparel_size;
    struct nlist32 *stksize;

    aout_initwrite(gv,sections);
    if (sections[0] == NULL)  /* this requires a .text section! */
        error(97,fff[gv->dest_format]->tname,TEXTNAME);

    memset(&me,0,sizeof(struct mint_exec));  /* init header with zero */
    text_data_bss_gaps(sections);  /* calculate gap size between sections */
    secsizes[0] = sections[0]->size + sections[0]->gapsize;
    secsizes[1] = sections[1] ? sections[1]->filesize : 0;

    /* init TOS header */
    write16be(me.tos.ph_branch,0x601a);
    write32be(me.tos.ph_tlen,secsizes[0]+TEXT_OFFSET);
    write32be(me.tos.ph_dlen,secsizes[1]);
    write32be(me.tos.ph_blen,(sections[2]?sections[2]->size:0) +
              (sections[1]?sections[1]->gapsize:0));
    write32be(me.tos.ph_magic,0x4d694e54);  /* "MiNT" */
    write32be(me.tos.ph_flags,gv->tosflags);  /* Atari memory flags */
    write16be(me.tos.ph_abs,0);  /* includes relocations */

    aout_addsymlist(gv,sections,BIND_GLOBAL,0,be);
    aout_addsymlist(gv,sections,BIND_WEAK,0,be);
    aout_addsymlist(gv,sections,BIND_LOCAL,0,be);
    aout_debugsyms(gv,be);
    calc_relocs(gv,sections[0]);
    calc_relocs(gv,sections[1]);

    /* The Atari symbol table size is the sum of a.out symbols and strings,
       which is now known. */
    write32be(me.tos.ph_slen,aoutsymlist.nextindex * sizeof(struct nlist32) +
              aoutstrlist.nextoffset);

    /* set jmp_entry to  move.l  a_entry(pc),d0
                         jmp     (-6,pc,d0.l)   */
    memcpy(me.jmp_entry,jmp_entry_code,sizeof(jmp_entry_code));

    /* init a.out NMAGIC header */
    SETMIDMAG(&me.aout,NMAGIC,0,0);
    write32be(me.aout.a_text,sections[0]->size+sections[0]->gapsize);
    write32be(me.aout.a_data,sections[1]?sections[1]->filesize:0);
    write32be(me.aout.a_bss,(sections[2]?sections[2]->size:0) +
              (sections[1]?sections[1]->gapsize:0));
    write32be(me.aout.a_syms,aoutsymlist.nextindex*sizeof(struct nlist32));
    write32be(me.aout.a_entry,TEXT_OFFSET);

    /* save offset to __stksize when symbol is present */
    if (stksize = find_aout_sym("__stksize")) {
        write32be(me.stkpos,
                  read32be(&stksize->n_value)+sizeof(me)-TEXT_OFFSET);
    }

    /* write a.out-MiNT header (256 bytes) */
    fwritex(f,&me,sizeof(me));

    /* write sections */
    fwritex(f,sections[0]->data,sections[0]->size);
    fwritegap(f,sections[0]->gapsize);
    if (sections[1])
        fwritex(f,sections[1]->data,sections[1]->filesize);

    /* write a.out symbols */
    aout_writesymbols(f);
    aout_writestrings(f,be);

    /* write TPA relocs */
    tparel_offset = ftell(f);
    tos_writerelocs(gv,f,sections);
    tparel_size = ftell(f) - tparel_offset;

    /* we have to patch tparel_pos and tparel_size in the header, as we
       didn't know about the size of the TPA relocs table before */
    fseek(f,offsetof(struct mint_exec,tparel_pos),SEEK_SET);
    fwrite32be(f,tparel_offset);
    fwrite32be(f,tparel_size);
}