ftp.nice.ch/pub/next/developer/languages/lisp/AKCL.1.599.s.tar.gz#/gas-1.38.1.hacked/atom.c

This is atom.c in view mode; [Download] [Up]

#include <stdio.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <varargs.h>
#include <a.out.h>
#include <sys/loader.h>
#define OBJC_SYM "__OBJC_SYMBOLS"
#define OBJC_MOD "__OBJC_MODULES"
#define OBJC_SEL "__OBJC_STRINGS"
#include <symseg.h>

/* The structures for mach relocatables */
struct mach_header		header;
struct segment_command		reloc_segment;
struct section			text_section;	/* __TEXT, __text */
struct section			data_section;	/* __DATA, __data */
struct section			bss_section;	/* __DATA, __bss */
struct section			sym_section;	/* __OBJC, __symbol_table */
struct section			mod_section;	/* __OBJC, __module_info */
struct section			sel_section;	/* __OBJC, __selector_strs */
struct symtab_command		symbol_table;
struct symseg_command		symbol_segment;

/*
 * The data relocation entried which are looked through to divide up into the
 * objective-C section's relocation entries and the data section's.
 */
struct relocation_info *data_reloc;
long data_reloff, data_nreloc;

a_out_to_mach_O(a_out, size_a_out, file_name, gdbsize, gdbpointer)
     char *a_out;
     int size_a_out;
     char *file_name;
     int gdbsize;
     char *gdbpointer;
{
  char *p, *ap;
  long header_size, fileoff, strsize;
  struct exec *exec;
  struct relocation_info *preloc;
  struct nlist *pnlist;
  struct symbol_root *psymbol_root;
  struct mach_root *pmach_root, mach_root;
  
  exec = (struct exec *)a_out;

  /*
   * For converted a.out files the resulting Mach-O object file will
   * look like:
   *
   *	mach header
   *	mach load commands
   *	the text segment
   *	the data segment
   *	the objective-C segment
   *	the relocation entries
   *	the 4.3bsd symbol table
   *	the 4.3bsd string table
   *	the gdb symbol segments
   */
  
  header.magic = MH_MAGIC;
  header.cputype = CPU_TYPE_MC680x0;
  header.cpusubtype = CPU_SUBTYPE_MC68040;
  header.filetype = MH_OBJECT;
  header.ncmds = 3;
  header.sizeofcmds =
    sizeof(struct segment_command) +
      6 * sizeof(struct section) +
	sizeof(struct symtab_command) +
	  sizeof(struct symseg_command);
  header.flags = 0;
  header_size = header.sizeofcmds + sizeof(struct mach_header);
  
  reloc_segment.cmd = LC_SEGMENT;
  reloc_segment.cmdsize = sizeof(struct segment_command) +
    6 * sizeof(struct section);
  /* leave reloc_segment.segname full of zeros */
  reloc_segment.vmaddr = 0;
  reloc_segment.vmsize = exec->a_text + exec->a_data + exec->a_bss;
  reloc_segment.fileoff = header_size;
  reloc_segment.filesize = exec->a_text + exec->a_data;
  reloc_segment.maxprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
  reloc_segment.initprot= VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
  reloc_segment.nsects = 6;
  reloc_segment.flags = 0;

  strcpy(text_section.sectname, SECT_TEXT);
  strcpy(text_section.segname, SEG_TEXT);
  text_section.addr = 0;
  text_section.size = exec->a_text;
  text_section.offset = header_size;
  text_section.align = 2;
  if(exec->a_trsize != 0) {
    text_section.reloff = header_size + exec->a_text + exec->a_data;
    text_section.nreloc = exec->a_trsize / sizeof (struct relocation_info);
  } else {
    text_section.reloff = 0;
    text_section.nreloc = 0;
  }
  text_section.flags = 0;
  text_section.reserved1 = 0;
  text_section.reserved2 = 0;
  
  strcpy(data_section.sectname, SECT_DATA);
  strcpy(data_section.segname, SEG_DATA);
  data_section.addr = exec->a_text;
  data_section.offset = header_size + exec->a_text;
  data_section.align = 2;
  data_section.flags = 0;
  data_section.reserved1 = 0;
  data_section.reserved2 = 0;

  strcpy(sym_section.sectname, SECT_OBJC_SYMBOLS);
  strcpy(sym_section.segname, SEG_OBJC);
  sym_section.align = 2;
  strcpy(mod_section.sectname, SECT_OBJC_MODULES);
  strcpy(mod_section.segname, SEG_OBJC);
  mod_section.align = 2;
  strcpy(sel_section.sectname, SECT_OBJC_STRINGS);
  strcpy(sel_section.segname, SEG_OBJC);
  sel_section.align = 2;
  
  /*
   * The symbols that start each of the objective-C sections have prevoiusly
   * been looked up in write.c and the addresses and sizes of these sections
   * has been set into the section structures.  These addresses are used to
   * to divide up the data section.  The assumptions are as follows:
   *		the data for these are at the end of the data section
   *		they are in the following order (if present)
   *			symbol table section
   *			module information section
   *			selector strings section
   */
  
  /*
   * Now knowing the sizes of all the objective-C sections the size
   * of the data section and the file offsets can be calculated.
   */
  data_section.size = exec->a_data -
    (sel_section.size + sym_section.size + mod_section.size);
  
  sym_section.offset = data_section.offset + data_section.size;
  mod_section.offset =  sym_section.offset + sym_section.size;
  sel_section.offset =  mod_section.offset + mod_section.size;
  
  /*
   * Now the data relocation entries have to be divided up.  This
   * is relying on the fact that the assembler produces relocation
   * entries in decreasing order based on the r_address field.  Note
   * the r_address field is really an offset into the section.
   */
  if(exec->a_drsize != 0) {
    data_reloc = (struct relocation_info *)xmalloc(exec->a_drsize);
    ap = a_out + N_TXTOFF(*exec) + exec->a_text + exec->a_data + exec->a_trsize;
    bcopy(ap, data_reloc, exec->a_drsize);
    data_reloff = header_size + exec->a_text + exec->a_data + exec->a_trsize;
    data_nreloc = exec->a_drsize / sizeof (struct relocation_info);
    
    data_section.reloff = data_reloff;
    data_section.nreloc = 0;
    sym_section.reloff  = data_reloff;
    sym_section.nreloc = 0;
    mod_section.reloff  = data_reloff;
    mod_section.nreloc = 0;
    sel_section.reloff  = data_reloff;
    sel_section.nreloc = 0;
    
    for(preloc = (struct relocation_info *)data_reloc;
	preloc < data_reloc + data_nreloc;
	preloc++){
      if(preloc->r_address >=
	 (data_section.addr + data_section.size) - exec->a_text)
	data_section.reloff += sizeof(struct relocation_info);
      else if(preloc->r_address >=
	      data_section.addr - exec->a_text)
	data_section.nreloc++;
      
      if(preloc->r_address >=
	 (sym_section.addr + sym_section.size) - exec->a_text)
	sym_section.reloff += sizeof(struct relocation_info);
      else if(preloc->r_address >=
	      sym_section.addr - exec->a_text)
	sym_section.nreloc++;
      
      if(preloc->r_address >=
	 (mod_section.addr + mod_section.size) - exec->a_text)
	mod_section.reloff += sizeof(struct relocation_info);
      else if(preloc->r_address >=
	      mod_section.addr - exec->a_text)
	mod_section.nreloc++;
      
      if(preloc->r_address >=
	 (sel_section.addr + sel_section.size) - exec->a_text)
	sel_section.reloff += sizeof(struct relocation_info);
      else if(preloc->r_address >=
	      sel_section.addr - exec->a_text)
	sel_section.nreloc++;
    }
  }
  else{
    data_section.reloff = 0;
    data_section.nreloc = 0;
    sym_section.reloff = 0;
    sym_section.nreloc = 0;
    mod_section.reloff = 0;
    mod_section.nreloc = 0;
    sel_section.reloff = 0;
    sel_section.nreloc = 0;
  }
  sym_section.flags = 0;
  sym_section.reserved1 = 0;
  sym_section.reserved2 = 0;

  mod_section.flags = 0;
  mod_section.reserved1 = 0;
  mod_section.reserved2 = 0;

  sel_section.flags = S_CSTRING_LITERALS;
  sel_section.reserved1 = 0;
  sel_section.reserved2 = 0;

  strcpy(bss_section.sectname, SECT_BSS);
  strcpy(bss_section.segname, SEG_DATA);
  bss_section.addr = exec->a_text + exec->a_data;
  bss_section.size = exec->a_bss;
  bss_section.offset = 0;
  bss_section.align = 2;
  bss_section.reloff = 0;
  bss_section.nreloc = 0;
  bss_section.flags = S_ZEROFILL;
  bss_section.reserved1 = 0;
  bss_section.reserved2 = 0;
  
  symbol_table.cmd = LC_SYMTAB;
  symbol_table.cmdsize = sizeof(struct symtab_command);
  symbol_table.symoff = 0;
  symbol_table.nsyms = 0;
  symbol_table.stroff = 0;
  symbol_table.strsize = 0;
  
  symbol_segment.cmd = LC_SYMSEG;
  symbol_segment.cmdsize = sizeof(struct symseg_command);
  symbol_segment.offset = 0;
  symbol_segment.size = 0;
  
  if(exec->a_syms != 0){
    fileoff = header_size + exec->a_text + exec->a_data + exec->a_trsize +
      exec->a_drsize;
    symbol_table.symoff = fileoff;
    symbol_table.nsyms = exec->a_syms / sizeof(struct nlist);
    fileoff += exec->a_syms;
    symbol_table.stroff = fileoff;

    p = a_out + N_STROFF(*exec);
    strsize = *(int *)p;
    symbol_table.strsize = strsize;
    fileoff += strsize;
    
    symbol_segment.cmd = LC_SYMSEG;
    symbol_segment.cmdsize = sizeof(struct symseg_command);
    symbol_segment.offset = fileoff;
    symbol_segment.size = gdbsize;
  }
  
  output_seek(0);
  output_write(&header, sizeof(struct mach_header));
  output_write(&reloc_segment, sizeof(struct segment_command));
  output_write(&text_section, sizeof(struct section));
  output_write(&data_section, sizeof(struct section));
  output_write(&bss_section, sizeof(struct section));
  output_write(&sym_section, sizeof(struct section));
  output_write(&mod_section, sizeof(struct section));
  output_write(&sel_section, sizeof(struct section));
  output_write(&symbol_table, sizeof(struct symtab_command));
  output_write(&symbol_segment, sizeof(struct symseg_command));

  /* leave the pad after the headers */
  output_seek(header_size);

  ap = a_out + N_TXTOFF(*exec);
  output_write(ap, exec->a_text);
  ap += exec->a_text;
  output_write(ap, exec->a_data);
  ap += exec->a_data;

  /*
   * The conversion of r_symbolnum is now done in emit_relocation() in
   * write.c.  This fixed a bug where the item to be relocated is symbol
   * plus offset and here we can't tell what the original symbol's address
   * is and we might use the wrong section number which will result an
   * incorrect relocation entry.
   */

  /* read and write the text relocation entries */
  if(exec->a_trsize != 0){
    p = ap;
    ap += exec->a_trsize;
    output_seek(text_section.reloff);
    output_write(p, exec->a_trsize);
  }
  
  /* read and write the data relocation entries */
  if(exec->a_drsize != 0){
    if (data_reloc != NULL) {
      p = (char *)data_reloc;
    } else {
      p = ap;
    }
    ap += exec->a_drsize;
    /* convert local relocation entries to Mach-O style */
    for(preloc = (struct relocation_info *)p;
	preloc < (struct relocation_info *)(p + exec->a_drsize);
	preloc++){
      /*
       * Adjust the r_address field (which is an
       * offset) to be an offset into the section that
       * the address it is refering to is in.
       */
      if(preloc->r_address >= sel_section.addr - exec->a_text)
	preloc->r_address -=
	  (sel_section.addr - data_section.addr);
      else if(preloc->r_address >= mod_section.addr - exec->a_text)
	preloc->r_address -=
	  (mod_section.addr - data_section.addr);
      else if(preloc->r_address >= sym_section.addr - exec->a_text)
	preloc->r_address -=
	  (sym_section.addr - data_section.addr);
      /* else its in the data section an it's fine as is*/
    }
    output_seek(data_reloff);
    output_write(p, exec->a_drsize);
  }
  
  /* read and write the symbol table */
  if(exec->a_syms != 0){
    p = ap;
    ap += exec->a_syms;
    /* convert symbol table entries to Mach-O style */
    for(pnlist = (struct nlist *)p;
	pnlist < (struct nlist *)(p + exec->a_syms);
	pnlist++){
      switch(pnlist->n_type & N_TYPE){
      case N_TEXT:
	pnlist->n_sect = 1;
	if((pnlist->n_type & N_STAB) == 0)
	  pnlist->n_type = N_SECT | (pnlist->n_type & N_EXT);
	break;
      case N_DATA:
	{
	  if(pnlist->n_value >= sel_section.addr + sel_section.size)
	    pnlist->n_sect = 2;
	  else if(pnlist->n_value >= sel_section.addr)
	    pnlist->n_sect = 6;
	  else if(pnlist->n_value >= mod_section.addr)
	    pnlist->n_sect = 5;
	  else if(pnlist->n_value >= sym_section.addr)
	    pnlist->n_sect = 4;
	  else
	    pnlist->n_sect = 2;
	}
	if((pnlist->n_type & N_STAB) == 0)
	  pnlist->n_type = N_SECT | (pnlist->n_type & N_EXT);
	break;
      case N_BSS:
	pnlist->n_sect = 3;
	if((pnlist->n_type & N_STAB) == 0)
	  pnlist->n_type = N_SECT | (pnlist->n_type & N_EXT);
	break;
      default:
	pnlist->n_sect = NO_SECT;
      }
    }
    output_seek(symbol_table.symoff);
    output_write(p, exec->a_syms);
  
    /* read and write the string table */
    p = ap;
    ap += strsize;
    output_seek(symbol_table.stroff);
    output_write(p, strsize);
  }
  
  /* read and write the symbol segment */
  if(symbol_segment.size != 0){
    p = ap;
    ap += symbol_segment.size;
    /*
     * Convert only the symbol_root to a mach_symbol_root.
     * This conversion is quite ugly.  It relies on the fact that
     * sizeof(struct symbol_root) - sizeof(struct mach_symbol_root)
     * 	>= sizeof(struct loadmap)
     * It replaces the symbol_root with a mach_symbol_root copying
     * the like fields.  Then it sets the loadmap pointer (offset
     * since it's in a file) to the end of the mach_symbol_root.
     * The load map is really just a struct loadmap field struct
     * with the nmaps field zero for a relocatable object.  It gets
     * the zero by bzero'ing the sizeof the symbol_root.  This also
     * assumes that in an OMAGIC file there is just one symbol_root.
     * I did say this was ugly.
     */
    p = gdbpointer;
    if(symbol_segment.size < sizeof(struct symbol_root))
      as_fatal("Invalid size of gdb symbol segment (smaller than a "
	    "symbol root)");
    psymbol_root = (struct symbol_root *)p;
    mach_root.format = MACH_ROOT_FORMAT;
    mach_root.length = psymbol_root->length;
    mach_root.ldsymoff = psymbol_root->ldsymoff;
    mach_root.filename = psymbol_root->filename;
    mach_root.filedir = psymbol_root->filedir;
    mach_root.blockvector = psymbol_root->blockvector;
    mach_root.typevector = psymbol_root->typevector;
    mach_root.language = psymbol_root->language;
    mach_root.version = psymbol_root->version;
    mach_root.compilation = psymbol_root->compilation;
    mach_root.sourcevector = psymbol_root->sourcevector;
    
    mach_root.loadmap =
      (struct loadmap *)(sizeof(struct mach_root));
    bzero(p, sizeof(struct symbol_root));
    pmach_root = (struct mach_root *)p;
    *pmach_root = mach_root;
    output_seek(symbol_segment.offset);
    output_write(p, symbol_segment.size);
  }
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.