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