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 <libintl.h>
36 : : #include <stdlib.h>
37 : : #include <string.h>
38 : :
39 : : #include <libasmP.h>
40 : : #include <libelf.h>
41 : : #include <system.h>
42 : :
43 : :
44 : : /* Memory for the default pattern. The type uses a flexible array
45 : : which does work well with a static initializer. So we play some
46 : : dirty tricks here. */
47 : : static const struct
48 : : {
49 : : struct FillPattern pattern;
50 : : char zero;
51 : : } xdefault_pattern =
52 : : {
53 : : .pattern =
54 : : {
55 : : .len = 1
56 : : },
57 : : .zero = '\0'
58 : : };
59 : : const struct FillPattern *__libasm_default_pattern = &xdefault_pattern.pattern;
60 : :
61 : :
62 : : static AsmScn_t *
63 : 0 : text_newscn (AsmScn_t *result, GElf_Word type, GElf_Xword flags)
64 : : {
65 : : /* Buffer where we construct the flag string. */
66 : 0 : char flagstr[sizeof (GElf_Xword) * 8 + 5];
67 : 0 : char *wp = flagstr;
68 : 0 : const char *typestr = "";
69 : :
70 : : /* Only write out the flag string if this is the first time the
71 : : section is selected. Some assemblers cannot cope with the
72 : : .section pseudo-op otherwise. */
73 [ # # ]: 0 : wp = stpcpy (wp, ", \"");
74 : :
75 [ # # ]: 0 : if (flags & SHF_WRITE)
76 : 0 : *wp++ = 'w';
77 [ # # ]: 0 : if (flags & SHF_ALLOC)
78 : 0 : *wp++ = 'a';
79 [ # # ]: 0 : if (flags & SHF_EXECINSTR)
80 : 0 : *wp++ = 'x';
81 [ # # ]: 0 : if (flags & SHF_MERGE)
82 : 0 : *wp++ = 'M';
83 [ # # ]: 0 : if (flags & SHF_STRINGS)
84 : 0 : *wp++ = 'S';
85 [ # # ]: 0 : if (flags & SHF_LINK_ORDER)
86 : 0 : *wp++ = 'L';
87 : :
88 : 0 : *wp++ = '"';
89 : :
90 [ # # ]: 0 : if (type == SHT_PROGBITS)
91 : : typestr = ",@progbits";
92 [ # # ]: 0 : else if (type == SHT_NOBITS)
93 : 0 : typestr = ",@nobits";
94 : :
95 : : /* Terminate the string. */
96 : 0 : *wp = '\0';
97 : :
98 : 0 : fprintf (result->ctx->out.file, "\t.section \"%s\"%s%s\n",
99 : 0 : result->name, flagstr, typestr);
100 : :
101 : 0 : return result;
102 : : }
103 : :
104 : :
105 : : static AsmScn_t *
106 : 176005 : binary_newscn (AsmScn_t *result, GElf_Word type, GElf_Xword flags,
107 : : size_t scnname_len)
108 : : {
109 : 176005 : GElf_Shdr shdr_mem;
110 : 176005 : GElf_Shdr *shdr;
111 : 176005 : Elf_Scn *scn;
112 : :
113 : : /* The initial subsection has the number zero. */
114 : 176005 : result->subsection_id = 0;
115 : :
116 : : /* We start at offset zero. */
117 : 176005 : result->offset = 0;
118 : : /* And generic alignment. */
119 : 176005 : result->max_align = 1;
120 : :
121 : : /* No output yet. */
122 : 176005 : result->content = NULL;
123 : :
124 : : /* Put the default fill pattern in place. */
125 : 176005 : result->pattern = (struct FillPattern *) __libasm_default_pattern;
126 : :
127 : : /* There are no subsections so far. */
128 : 176005 : result->subnext = NULL;
129 : :
130 : : /* Add the name to the section header string table. */
131 : 528015 : result->data.main.strent = dwelf_strtab_add_len (result->ctx->section_strtab,
132 : 176005 : result->name, scnname_len);
133 [ - + ]: 176005 : assert (result->data.main.strent != NULL);
134 : :
135 : : /* Create the new ELF section. */
136 : 176005 : result->data.main.scn = scn = elf_newscn (result->ctx->out.elf);
137 [ - + ]: 176005 : if (scn == NULL)
138 : : {
139 : 0 : free (result);
140 : 0 : __libasm_seterrno (ASM_E_LIBELF);
141 : 0 : return NULL;
142 : : }
143 : :
144 : : /* Not part of a section group (yet). */
145 : 176005 : result->data.main.next_in_group = NULL;
146 : :
147 : : /* Remember the flags. */
148 : 176005 : shdr = gelf_getshdr (scn, &shdr_mem);
149 : :
150 : 176005 : shdr->sh_flags = flags;
151 : 176005 : result->type = shdr->sh_type = type;
152 : :
153 : 176005 : (void) gelf_update_shdr (scn, shdr);
154 : :
155 : 176005 : return result;
156 : : }
157 : :
158 : :
159 : : AsmScn_t *
160 : 176005 : asm_newscn (AsmCtx_t *ctx, const char *scnname, GElf_Word type,
161 : : GElf_Xword flags)
162 : : {
163 : 176005 : size_t scnname_len = strlen (scnname) + 1;
164 : 176005 : AsmScn_t *result;
165 : :
166 : : /* If no context is given there might be an earlier error. */
167 [ + - ]: 176005 : if (ctx == NULL)
168 : : return NULL;
169 : :
170 : : /* Check whether only flags are set which areselectable by the user. */
171 [ + - ]: 176005 : if (unlikely ((flags & ~(SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE
172 : : | SHF_STRINGS | SHF_LINK_ORDER)) != 0)
173 : : /* We allow only two section types: data and data without file
174 : : representation. */
175 [ - + # # ]: 176005 : || (type != SHT_PROGBITS && unlikely (type != SHT_NOBITS)))
176 : : {
177 : 0 : __libasm_seterrno (ASM_E_INVALID);
178 : 0 : return NULL;
179 : : }
180 : :
181 : 176005 : rwlock_wrlock (ctx->lock);
182 : :
183 : : /* This is a new section. */
184 : 176005 : result = (AsmScn_t *) malloc (sizeof (AsmScn_t) + scnname_len);
185 [ + - ]: 176005 : if (result != NULL)
186 : : {
187 : : /* Add the name. */
188 [ - + ]: 176005 : memcpy (result->name, scnname, scnname_len);
189 : :
190 : : /* Add the reference to the context. */
191 : 176005 : result->ctx = ctx;
192 : :
193 : : /* Perform operations according to output mode. */
194 : 352010 : result = (unlikely (ctx->textp)
195 : 0 : ? text_newscn (result, type, flags)
196 [ - + ]: 176005 : : binary_newscn (result, type, flags, scnname_len));
197 : :
198 : : /* If everything went well finally add the new section to the hash
199 : : table. */
200 [ + - ]: 176005 : if (result != NULL)
201 : : {
202 : 176005 : result->allnext = ctx->section_list;
203 : 176005 : ctx->section_list = result;
204 : : }
205 : : }
206 : :
207 : : rwlock_unlock (ctx->lock);
208 : :
209 : : return result;
210 : : }
211 : : INTDEF(asm_newscn)
|