• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Align section.
2    Copyright (C) 2002 Red Hat, Inc.
3    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
4 
5    This program is Open Source software; you can redistribute it and/or
6    modify it under the terms of the Open Software License version 1.0 as
7    published by the Open Source Initiative.
8 
9    You should have received a copy of the Open Software License along
10    with this program; if not, you may obtain a copy of the Open Software
11    License version 1.0 from http://www.opensource.org/licenses/osl.php or
12    by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
13    3001 King Ranch Road, Ukiah, CA 95482.   */
14 
15 #ifdef HAVE_CONFIG_H
16 # include <config.h>
17 #endif
18 
19 #include <stdlib.h>
20 #include <sys/param.h>
21 
22 #include <libasmP.h>
23 #include <system.h>
24 
25 
26 int
asm_align(asmscn,value)27 asm_align (asmscn, value)
28      AsmScn_t *asmscn;
29      GElf_Word value;
30 {
31   if (asmscn == NULL)
32     /* An earlier error.  */
33     return -1;
34 
35       /* The alignment value must be a power of two.  */
36   if (unlikely (! powerof2 (value)))
37     {
38       __libasm_seterrno (ASM_E_INVALID);
39       return -1;
40     }
41 
42   rwlock_wrlock (asmscn->ctx->lock);
43 
44   int result = 0;
45 
46   /* Fillbytes necessary?  */
47   if ((asmscn->offset & (value - 1)) != 0)
48     {
49       /* Add fillbytes.  */
50       size_t cnt;
51       size_t byteptr;
52 
53       cnt = value - (asmscn->offset & (value - 1));
54 
55       /* Ensure there is enough room to add the fill bytes.  */
56       result = __libasm_ensure_section_space (asmscn, cnt);
57       if (result != 0)
58 	goto out;
59 
60       /* Fill in the bytes.  We align the pattern according to the
61 	 current offset.  */
62       byteptr = asmscn->offset % asmscn->pattern->len;
63 
64       /* Update the total size.  */
65       asmscn->offset += cnt;
66 
67       do
68 	{
69 	  asmscn->content->data[asmscn->content->len++]
70 	    = asmscn->pattern->bytes[byteptr++];
71 
72 	  if (byteptr == asmscn->pattern->len)
73 	    byteptr = 0;
74 	}
75       while (--cnt > 0);
76     }
77 
78   /* Remember the maximum alignment for this subsection.  */
79   if (asmscn->max_align < value)
80     {
81       asmscn->max_align = value;
82 
83       /* Update the parent as well (if it exists).  */
84       if (asmscn->subsection_id != 0)
85 	{
86 	  rwlock_wrlock (asmscn->data.up->ctx->lock);
87 
88 	  if (asmscn->data.up->max_align < value)
89 	    asmscn->data.up->max_align = value;
90 
91 	  rwlock_unlock (asmscn->data.up->ctx->lock);
92 	}
93     }
94 
95  out:
96   rwlock_unlock (asmscn->ctx->lock);
97 
98   return result;
99 }
100 
101 
102 /* Ensure there are at least LEN bytes available in the output buffer
103    for ASMSCN.  */
104 int
__libasm_ensure_section_space(asmscn,len)105 __libasm_ensure_section_space (asmscn, len)
106      AsmScn_t *asmscn;
107      size_t len;
108 {
109   /* The blocks with the section content are kept in a circular
110      single-linked list.  */
111   size_t size;
112 
113   if (asmscn->content == NULL)
114     {
115       /* This is the first block.  */
116       size = MAX (2 * len, 960);
117 
118       asmscn->content = (struct AsmData *) malloc (sizeof (struct AsmData)
119 						   + size);
120       if (asmscn->content == NULL)
121 	return -1;
122 
123       asmscn->content->next = asmscn->content;
124     }
125   else
126     {
127       struct AsmData *newp;
128 
129       if (asmscn->content->maxlen - asmscn->content->len >= len)
130 	/* Nothing to do, there is enough space.  */
131 	return 0;
132 
133       size = MAX (2 *len, MIN (32768, 2 * asmscn->offset));
134 
135       newp = (struct AsmData *) malloc (sizeof (struct AsmData) + size);
136       if (newp == NULL)
137 	return -1;
138 
139       newp->next = asmscn->content->next;
140       asmscn->content = asmscn->content->next = newp;
141     }
142 
143   asmscn->content->len = 0;
144   asmscn->content->maxlen = size;
145 
146   return 0;
147 }
148