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