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