Home | History | Annotate | Download | only in libasm
      1 /* Create descriptor for assembling.
      2    Copyright (C) 2002 Red Hat, Inc.
      3    Written by Ulrich Drepper <drepper (at) redhat.com>, 2002.
      4 
      5    This program is Open Source software; you can redistribute it and/or
      6    modify it under the terms of the Open Software License version 1.0 as
      7    published by the Open Source Initiative.
      8 
      9    You should have received a copy of the Open Software License along
     10    with this program; if not, you may obtain a copy of the Open Software
     11    License version 1.0 from http://www.opensource.org/licenses/osl.php or
     12    by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
     13    3001 King Ranch Road, Ukiah, CA 95482.   */
     14 
     15 #ifdef HAVE_CONFIG_H
     16 # include <config.h>
     17 #endif
     18 
     19 #include <assert.h>
     20 #include <errno.h>
     21 #include <stdlib.h>
     22 #include <string.h>
     23 #include <unistd.h>
     24 
     25 #include <gelf.h>
     26 #include "libasmP.h"
     27 #include <system.h>
     28 
     29 
     30 static AsmCtx_t *
     31 prepare_text_output (AsmCtx_t *result)
     32 {
     33   return result;
     34 }
     35 
     36 
     37 static AsmCtx_t *
     38 prepare_binary_output (AsmCtx_t *result, int machine, int klass, int data)
     39 {
     40   GElf_Ehdr *ehdr;
     41   GElf_Ehdr ehdr_mem;
     42 
     43   /* Create the ELF descriptor for the file.  */
     44   result->out.elf = elf_begin (result->fd, ELF_C_WRITE_MMAP, NULL);
     45   if (result->out.elf == NULL)
     46     {
     47     err_libelf:
     48       unlink (result->tmp_fname);
     49       close (result->fd);
     50       free (result);
     51       __libasm_seterrno (ASM_E_LIBELF);
     52       return NULL;
     53     }
     54 
     55   /* Create the ELF header for the output file.  */
     56   if (gelf_newehdr (result->out.elf, klass) == 0)
     57     goto err_libelf;
     58 
     59   ehdr = gelf_getehdr (result->out.elf, &ehdr_mem);
     60   /* If this failed we are in trouble.  */
     61   assert (ehdr != NULL);
     62 
     63   /* We create an object file.  */
     64   ehdr->e_type = ET_REL;
     65   /* Set the ELF version.  */
     66   ehdr->e_version = EV_CURRENT;
     67 
     68   /* Use the machine value the user provided.  */
     69   ehdr->e_machine = machine;
     70   /* Same for the class and endianness.  */
     71   ehdr->e_ident[EI_CLASS] = klass;
     72   ehdr->e_ident[EI_DATA] = data;
     73 
     74   memcpy (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG);
     75 
     76   /* Write the ELF header information back.  */
     77   (void) gelf_update_ehdr (result->out.elf, ehdr);
     78 
     79   /* No section so far.  */
     80   result->section_list = NULL;
     81 
     82   /* Initialize the hash table.  */
     83   asm_symbol_tab_init (&result->symbol_tab, 67);
     84   result->nsymbol_tab = 0;
     85   /* And the string tables.  */
     86   result->section_strtab = ebl_strtabinit (true);
     87   result->symbol_strtab = ebl_strtabinit (true);
     88 
     89   /* We have no section groups so far.  */
     90   result->groups = NULL;
     91   result->ngroups = 0;
     92 
     93   return result;
     94 }
     95 
     96 
     97 AsmCtx_t *
     98 asm_begin (fname, textp, machine, klass, data)
     99      const char *fname;
    100      bool textp;
    101      int machine;
    102      int klass;
    103      int data;
    104 {
    105   size_t fname_len = strlen (fname);
    106   AsmCtx_t *result;
    107 
    108 
    109   /* First order of business: find the appropriate backend.  If it
    110      does not exist we don't have to look further.  */
    111   // XXX
    112 
    113   /* Create the file descriptor.  We do not generate the output file
    114      right away.  Instead we create a temporary file in the same
    115      directory which, if everything goes alright, will replace a
    116      possibly existing file with the given name.  */
    117   result = (AsmCtx_t *) malloc (sizeof (AsmCtx_t) + 2 * fname_len + 9);
    118   if (result == NULL)
    119     return NULL;
    120 
    121   /* Initialize the lock.  */
    122   rwlock_init (result->lock);
    123 
    124   /* Create the name of the temporary file.  */
    125   result->fname = stpcpy (mempcpy (result->tmp_fname, fname, fname_len),
    126 			  ".XXXXXX") + 1;
    127   memcpy (result->fname, fname, fname_len + 1);
    128 
    129   /* Create the temporary file.  */
    130   result->fd = mkstemp (result->tmp_fname);
    131   if (result->fd == -1)
    132     {
    133       int save_errno = errno;
    134       free (result);
    135       __libasm_seterrno (ASM_E_CANNOT_CREATE);
    136       errno = save_errno;
    137       return NULL;
    138     }
    139 
    140   /* Initialize the counter for temporary symbols.  */
    141   result->tempsym_count = 0;
    142 
    143   /* Now we differentiate between textual and binary output.   */
    144   result->textp = textp;
    145   if (textp)
    146     result = prepare_text_output (result);
    147   else
    148     result = prepare_binary_output (result, machine, klass, data);
    149 
    150   return result;
    151 }
    152