Merge all the collect and kmodsrc-* directories into one.
[ksplice.git] / objcommon.c
blobbeede28bbf5dc4c80a71db7fdaeaceb714c327f9
1 /* Copyright (C) 2008 Jeffrey Brian Arnold <jbarnold@mit.edu>
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License, version 2.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
14 * 02110-1301, USA.
17 #include "objcommon.h"
19 void vec_do_reserve(void **data, size_t *mem_size, size_t new_size)
21 if (new_size > *mem_size || new_size * 2 < *mem_size) {
22 if (new_size < *mem_size * 2)
23 new_size = *mem_size * 2;
24 *data = realloc(*data, new_size);
25 assert(new_size == 0 || *data != NULL);
26 *mem_size = new_size;
30 void get_syms(bfd *abfd, struct asymbolp_vec *syms)
32 long storage_needed = bfd_get_symtab_upper_bound(abfd);
33 if (storage_needed == 0)
34 return;
35 assert(storage_needed >= 0);
37 vec_init(syms);
38 vec_reserve(syms, storage_needed);
39 vec_resize(syms, bfd_canonicalize_symtab(abfd, syms->data));
40 assert(syms->size >= 0);
43 struct supersect *fetch_supersect(bfd *abfd, asection *sect,
44 struct asymbolp_vec *syms)
46 if (sect->userdata != NULL)
47 return sect->userdata;
49 struct supersect *new = malloc(sizeof(*new));
50 sect->userdata = new;
51 new->parent = abfd;
52 new->name = malloc(strlen(sect->name) + 1);
53 strcpy(new->name, sect->name);
54 new->flags = bfd_get_section_flags(abfd, sect);
56 vec_init(&new->contents);
57 vec_resize(&new->contents, bfd_get_section_size(sect));
58 assert(bfd_get_section_contents
59 (abfd, sect, new->contents.data, 0, new->contents.size));
60 new->alignment = bfd_get_section_alignment(abfd, sect);
62 vec_init(&new->relocs);
63 vec_reserve(&new->relocs, bfd_get_reloc_upper_bound(abfd, sect));
64 vec_resize(&new->relocs,
65 bfd_canonicalize_reloc(abfd, sect, new->relocs.data,
66 syms->data));
67 assert(new->relocs.size >= 0);
68 vec_init(&new->new_relocs);
70 return new;
73 struct supersect *new_supersects = NULL;
75 struct supersect *new_supersect(char *name)
77 struct supersect *ss;
78 for (ss = new_supersects; ss != NULL; ss = ss->next) {
79 if (strcmp(name, ss->name) == 0)
80 return ss;
83 struct supersect *new = malloc(sizeof(*new));
84 new->parent = NULL;
85 new->name = name;
86 new->next = new_supersects;
87 new_supersects = new;
88 new->flags = SEC_ALLOC | SEC_HAS_CONTENTS | SEC_RELOC;
90 vec_init(&new->contents);
91 new->alignment = 0;
92 vec_init(&new->relocs);
93 vec_init(&new->new_relocs);
95 return new;
98 void *sect_do_grow(struct supersect *ss, size_t n, size_t size, int alignment)
100 if (ss->alignment < ffs(alignment) - 1)
101 ss->alignment = ffs(alignment) - 1;
102 int pad = ss->contents.size - align(ss->contents.size, alignment);
103 void *out = vec_grow(&ss->contents, pad + n * size);
104 memset(out, 0, pad + n * size);
105 return out + pad;
108 bfd_vma addr_offset(struct supersect *ss, void *addr)
110 return (void *)addr - ss->contents.data;
113 bfd_vma get_reloc_offset(struct supersect *ss, arelent *reloc, int adjust_pc)
115 int size = bfd_get_reloc_size(reloc->howto);
117 bfd_vma x = bfd_get(size * 8, ss->parent,
118 ss->contents.data + reloc->address);
119 x &= reloc->howto->src_mask;
120 x >>= reloc->howto->bitpos;
121 bfd_vma signbit = reloc->howto->dst_mask >> reloc->howto->bitpos;
122 signbit &= ~(signbit >> 1);
123 switch (reloc->howto->complain_on_overflow) {
124 case complain_overflow_signed:
125 case complain_overflow_bitfield:
126 x |= -(x & signbit);
127 break;
128 case complain_overflow_unsigned:
129 break;
130 default:
131 DIE;
133 x <<= reloc->howto->rightshift;
135 bfd_vma add = reloc->addend;
136 if (reloc->howto->pc_relative) {
137 if (!reloc->howto->pcrel_offset)
138 add += reloc->address;
139 if (adjust_pc)
140 add += size;
142 return x + add;