Branch data Line data Source code
1 : : /* Create new section in output file.
2 : : Copyright (C) 2002-2011, 2016 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : : Written by Ulrich Drepper <drepper@redhat.com>, 2002.
5 : :
6 : : This file is free software; you can redistribute it and/or modify
7 : : it under the terms of either
8 : :
9 : : * the GNU Lesser General Public License as published by the Free
10 : : Software Foundation; either version 3 of the License, or (at
11 : : your option) any later version
12 : :
13 : : or
14 : :
15 : : * the GNU General Public License as published by the Free
16 : : Software Foundation; either version 2 of the License, or (at
17 : : your option) any later version
18 : :
19 : : or both in parallel, as here.
20 : :
21 : : elfutils is distributed in the hope that it will be useful, but
22 : : WITHOUT ANY WARRANTY; without even the implied warranty of
23 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 : : General Public License for more details.
25 : :
26 : : You should have received copies of the GNU General Public License and
27 : : the GNU Lesser General Public License along with this program. If
28 : : not, see <http://www.gnu.org/licenses/>. */
29 : :
30 : : #ifdef HAVE_CONFIG_H
31 : : # include <config.h>
32 : : #endif
33 : :
34 : : #include <assert.h>
35 : : #include <stdlib.h>
36 : : #include <string.h>
37 : :
38 : : #include <libasmP.h>
39 : : #include <libelf.h>
40 : : #include <system.h>
41 : :
42 : :
43 : : /* Memory for the default pattern. The type uses a flexible array
44 : : which does work well with a static initializer. Work around this by
45 : : wrapping it in a union, whose second member is a char array 1 byte larger
46 : : than struct FillPattern. According to 6.7.9, this does what we need:
47 : :
48 : : If an object that has static or thread storage duration is not
49 : : initialized explicitly, then ... if it is a union, the first named
50 : : member is initialized (recursively) according to these rules, and
51 : : any padding is initialized to zero bits. */
52 : :
53 : : static const union
54 : : {
55 : : struct FillPattern pattern;
56 : : char zeroes[sizeof(struct FillPattern) + 1];
57 : : } xdefault_pattern =
58 : : {
59 : : .pattern =
60 : : {
61 : : .len = 1
62 : : },
63 : : };
64 : : const struct FillPattern *__libasm_default_pattern = &xdefault_pattern.pattern;
65 : :
66 : :
67 : : static AsmScn_t *
68 : 0 : text_newscn (AsmScn_t *result, GElf_Word type, GElf_Xword flags)
69 : : {
70 : : /* Buffer where we construct the flag string. */
71 : 0 : char flagstr[sizeof (GElf_Xword) * 8 + 5];
72 : 0 : char *wp = flagstr;
73 : 0 : const char *typestr = "";
74 : :
75 : : /* Only write out the flag string if this is the first time the
76 : : section is selected. Some assemblers cannot cope with the
77 : : .section pseudo-op otherwise. */
78 [ # # ]: 0 : wp = stpcpy (wp, ", \"");
79 : :
80 [ # # ]: 0 : if (flags & SHF_WRITE)
81 : 0 : *wp++ = 'w';
82 [ # # ]: 0 : if (flags & SHF_ALLOC)
83 : 0 : *wp++ = 'a';
84 [ # # ]: 0 : if (flags & SHF_EXECINSTR)
85 : 0 : *wp++ = 'x';
86 [ # # ]: 0 : if (flags & SHF_MERGE)
87 : 0 : *wp++ = 'M';
88 [ # # ]: 0 : if (flags & SHF_STRINGS)
89 : 0 : *wp++ = 'S';
90 [ # # ]: 0 : if (flags & SHF_LINK_ORDER)
91 : 0 : *wp++ = 'L';
92 : :
93 : 0 : *wp++ = '"';
94 : :
95 [ # # ]: 0 : if (type == SHT_PROGBITS)
96 : : typestr = ",@progbits";
97 [ # # ]: 0 : else if (type == SHT_NOBITS)
98 : 0 : typestr = ",@nobits";
99 : :
100 : : /* Terminate the string. */
101 : 0 : *wp = '\0';
102 : :
103 : 0 : fprintf (result->ctx->out.file, "\t.section \"%s\"%s%s\n",
104 : 0 : result->name, flagstr, typestr);
105 : :
106 : 0 : return result;
107 : : }
108 : :
109 : :
110 : : static AsmScn_t *
111 : 176005 : binary_newscn (AsmScn_t *result, GElf_Word type, GElf_Xword flags,
112 : : size_t scnname_len)
113 : : {
114 : 176005 : GElf_Shdr shdr_mem;
115 : 176005 : GElf_Shdr *shdr;
116 : 176005 : Elf_Scn *scn;
117 : :
118 : : /* The initial subsection has the number zero. */
119 : 176005 : result->subsection_id = 0;
120 : :
121 : : /* We start at offset zero. */
122 : 176005 : result->offset = 0;
123 : : /* And generic alignment. */
124 : 176005 : result->max_align = 1;
125 : :
126 : : /* No output yet. */
127 : 176005 : result->content = NULL;
128 : :
129 : : /* Put the default fill pattern in place. */
130 : 176005 : result->pattern = (struct FillPattern *) __libasm_default_pattern;
131 : :
132 : : /* There are no subsections so far. */
133 : 176005 : result->subnext = NULL;
134 : :
135 : : /* Add the name to the section header string table. */
136 : 352010 : result->data.main.strent = dwelf_strtab_add_len (result->ctx->section_strtab,
137 : 176005 : result->name, scnname_len);
138 [ - + ]: 176005 : assert (result->data.main.strent != NULL);
139 : :
140 : : /* Create the new ELF section. */
141 : 176005 : result->data.main.scn = scn = elf_newscn (result->ctx->out.elf);
142 [ - + ]: 176005 : if (scn == NULL)
143 : : {
144 : 0 : free (result);
145 : 0 : __libasm_seterrno (ASM_E_LIBELF);
146 : 0 : return NULL;
147 : : }
148 : :
149 : : /* Not part of a section group (yet). */
150 : 176005 : result->data.main.next_in_group = NULL;
151 : :
152 : : /* Remember the flags. */
153 : 176005 : shdr = gelf_getshdr (scn, &shdr_mem);
154 : :
155 : 176005 : shdr->sh_flags = flags;
156 : 176005 : result->type = shdr->sh_type = type;
157 : :
158 : 176005 : (void) gelf_update_shdr (scn, shdr);
159 : :
160 : 176005 : return result;
161 : : }
162 : :
163 : :
164 : : AsmScn_t *
165 : 176005 : asm_newscn (AsmCtx_t *ctx, const char *scnname, GElf_Word type,
166 : : GElf_Xword flags)
167 : : {
168 : 176005 : size_t scnname_len = strlen (scnname) + 1;
169 : 176005 : AsmScn_t *result;
170 : :
171 : : /* If no context is given there might be an earlier error. */
172 [ + - ]: 176005 : if (ctx == NULL)
173 : : return NULL;
174 : :
175 : : /* Check whether only flags are set which areselectable by the user. */
176 [ + - ]: 176005 : if (unlikely ((flags & ~(SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE
177 : : | SHF_STRINGS | SHF_LINK_ORDER)) != 0)
178 : : /* We allow only two section types: data and data without file
179 : : representation. */
180 [ - + - - ]: 176005 : || (type != SHT_PROGBITS && unlikely (type != SHT_NOBITS)))
181 : : {
182 : 0 : __libasm_seterrno (ASM_E_INVALID);
183 : 0 : return NULL;
184 : : }
185 : :
186 : 176005 : rwlock_wrlock (ctx->lock);
187 : :
188 : : /* This is a new section. */
189 : 176005 : result = malloc (sizeof (AsmScn_t) + scnname_len);
190 [ + - ]: 176005 : if (result != NULL)
191 : : {
192 : : /* Add the name. */
193 [ - + ]: 176005 : memcpy (result->name, scnname, scnname_len);
194 : :
195 : : /* Add the reference to the context. */
196 : 176005 : result->ctx = ctx;
197 : :
198 : : /* Perform operations according to output mode. */
199 : 352010 : result = (unlikely (ctx->textp)
200 : 0 : ? text_newscn (result, type, flags)
201 [ - + ]: 176005 : : binary_newscn (result, type, flags, scnname_len));
202 : :
203 : : /* If everything went well finally add the new section to the hash
204 : : table. */
205 [ + - ]: 176005 : if (result != NULL)
206 : : {
207 : 176005 : result->allnext = ctx->section_list;
208 : 176005 : ctx->section_list = result;
209 : : }
210 : : }
211 : :
212 : : rwlock_unlock (ctx->lock);
213 : :
214 : : return result;
215 : : }
216 : : INTDEF(asm_newscn)
|