Branch data Line data Source code
1 : : /* Align section.
2 : : Copyright (C) 2002, 2005 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 <inttypes.h>
35 : : #include <stdlib.h>
36 : : #include <sys/param.h>
37 : :
38 : : #include <libasmP.h>
39 : : #include <system.h>
40 : :
41 : :
42 : : int
43 : 4 : asm_align (asmscn, value)
44 : : AsmScn_t *asmscn;
45 : : GElf_Word value;
46 : : {
47 [ + - ]: 4 : if (asmscn == NULL)
48 : : /* An earlier error. */
49 : : return -1;
50 : :
51 : : /* The alignment value must be a power of two. */
52 [ - + ]: 4 : if (unlikely (! powerof2 (value)))
53 : : {
54 : 0 : __libasm_seterrno (ASM_E_INVALID);
55 : 0 : return -1;
56 : : }
57 : :
58 [ - + ]: 4 : if (unlikely (asmscn->ctx->textp))
59 : : {
60 : 0 : fprintf (asmscn->ctx->out.file, "\t.align %" PRId32 ", ",
61 : : (int32_t) value);
62 [ # # ]: 0 : if (asmscn->pattern->len == 1)
63 : 0 : fprintf (asmscn->ctx->out.file, "%02hhx\n", asmscn->pattern->bytes[0]);
64 : : else
65 : : {
66 : 0 : fputc_unlocked ('"', asmscn->ctx->out.file);
67 : :
68 [ # # ]: 0 : for (size_t cnt = 0; cnt < asmscn->pattern->len; ++cnt)
69 : 0 : fprintf (asmscn->ctx->out.file, "\\x%02hhx",
70 : 0 : asmscn->pattern->bytes[cnt]);
71 : :
72 : 0 : fputs_unlocked ("\"\n", asmscn->ctx->out.file);
73 : : }
74 : : return 0;
75 : : }
76 : :
77 : : rwlock_wrlock (asmscn->ctx->lock);
78 : :
79 : 4 : int result = 0;
80 : :
81 : : /* Fillbytes necessary? */
82 [ - + ]: 4 : if ((asmscn->offset & (value - 1)) != 0)
83 : : {
84 : : /* Add fillbytes. */
85 : 0 : size_t cnt = value - (asmscn->offset & (value - 1));
86 : :
87 : : /* Ensure there is enough room to add the fill bytes. */
88 : 0 : result = __libasm_ensure_section_space (asmscn, cnt);
89 [ # # ]: 0 : if (result != 0)
90 : : goto out;
91 : :
92 : : /* Fill in the bytes. We align the pattern according to the
93 : : current offset. */
94 : 0 : size_t byteptr = asmscn->offset % asmscn->pattern->len;
95 : :
96 : : /* Update the total size. */
97 : 0 : asmscn->offset += cnt;
98 : :
99 : : do
100 : : {
101 : 0 : asmscn->content->data[asmscn->content->len++]
102 : 0 : = asmscn->pattern->bytes[byteptr++];
103 : :
104 [ # # ]: 0 : if (byteptr == asmscn->pattern->len)
105 : 0 : byteptr = 0;
106 : : }
107 [ # # ]: 0 : while (--cnt > 0);
108 : : }
109 : :
110 : : /* Remember the maximum alignment for this subsection. */
111 [ + - ]: 4 : if (asmscn->max_align < value)
112 : : {
113 : 4 : asmscn->max_align = value;
114 : :
115 : : /* Update the parent as well (if it exists). */
116 [ - + ]: 4 : if (asmscn->subsection_id != 0)
117 : : {
118 : : rwlock_wrlock (asmscn->data.up->ctx->lock);
119 : :
120 [ # # ]: 0 : if (asmscn->data.up->max_align < value)
121 : 0 : asmscn->data.up->max_align = value;
122 : :
123 : : rwlock_unlock (asmscn->data.up->ctx->lock);
124 : : }
125 : : }
126 : :
127 : : out:
128 : : rwlock_unlock (asmscn->ctx->lock);
129 : :
130 : 4 : return result;
131 : : }
132 : :
133 : :
134 : : /* Ensure there are at least LEN bytes available in the output buffer
135 : : for ASMSCN. */
136 : : int
137 : 176038 : __libasm_ensure_section_space (asmscn, len)
138 : : AsmScn_t *asmscn;
139 : : size_t len;
140 : : {
141 : : /* The blocks with the section content are kept in a circular
142 : : single-linked list. */
143 : : size_t size;
144 : :
145 [ + + ]: 176038 : if (asmscn->content == NULL)
146 : : {
147 : : /* This is the first block. */
148 : 176005 : size = MAX (2 * len, 960);
149 : :
150 : 176005 : asmscn->content = (struct AsmData *) malloc (sizeof (struct AsmData)
151 : : + size);
152 [ + - ]: 176005 : if (asmscn->content == NULL)
153 : : return -1;
154 : :
155 : 176005 : asmscn->content->next = asmscn->content;
156 : : }
157 : : else
158 : : {
159 : : struct AsmData *newp;
160 : :
161 [ - + ]: 33 : if (asmscn->content->maxlen - asmscn->content->len >= len)
162 : : /* Nothing to do, there is enough space. */
163 : : return 0;
164 : :
165 : 0 : size = MAX (2 *len, MIN (32768, 2 * asmscn->offset));
166 : :
167 : 0 : newp = (struct AsmData *) malloc (sizeof (struct AsmData) + size);
168 [ # # ]: 0 : if (newp == NULL)
169 : : return -1;
170 : :
171 : 0 : newp->next = asmscn->content->next;
172 : 0 : asmscn->content = asmscn->content->next = newp;
173 : : }
174 : :
175 : 176005 : asmscn->content->len = 0;
176 : 176005 : asmscn->content->maxlen = size;
177 : :
178 : 176038 : return 0;
179 : : }
|