• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Create descriptor for assembling.
2    Copyright (C) 2002 Red Hat, Inc.
3    Written by Ulrich Drepper <drepper@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 *
prepare_text_output(AsmCtx_t * result)31 prepare_text_output (AsmCtx_t *result)
32 {
33   return result;
34 }
35 
36 
37 static AsmCtx_t *
prepare_binary_output(AsmCtx_t * result,int machine,int klass,int data)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 *
asm_begin(fname,textp,machine,klass,data)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