blob: 22356d56d8a858a067e7f744457d3f1bdb4bc5d5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
#include <stdlib.h>
#include <merror.h>
#include "link.h"
#define SEGTAB_INIT_SIZE 8
int segtab_init(struct segment_table *segtab)
{
segtab->len = 0;
segtab->size = SEGTAB_INIT_SIZE;
segtab->entries = malloc(sizeof(struct segment_table_entry) *
SEGTAB_INIT_SIZE);
if (segtab->entries == NULL) {
PERROR("cannot alloc");
return M_ERROR;
}
return M_SUCCESS;
}
void segtab_free(struct segment_table *segtab)
{
for (uint32_t i = 0; i < segtab->len; i++) {
segtab_ent_free(&segtab->entries[i]);
}
free(segtab->entries);
}
/* create a new entry with <seg> as its first segment part */
int segtab_push(struct segment_table *segtab, struct segment_table_entry **res,
struct segment *seg)
{
if (segtab->len >= segtab->size) {
uint32_t size = segtab->size * 2;
void *new = realloc(segtab->entries,
sizeof(struct segment_table_entry) * size);
if (new == NULL) {
PERROR("cannot relloc");
return M_ERROR;
}
segtab->size = size;
segtab->entries = new;
}
struct segment_table_entry ent;
if (segtab_ent_init(&ent))
return M_ERROR;
ent.name = seg->name;
ent.vaddr = seg->vaddr;
ent.off = seg->off;
if (segtab_ent_push(&ent, seg)) {
segtab_ent_free(&ent);
return M_ERROR;
}
segtab->entries[segtab->len] = ent;
if (res != NULL)
*res = &segtab->entries[segtab->len];
segtab->len++;
return M_SUCCESS;
}
/* find a segment table entry with a given name */
int segtab_get(struct segment_table *segtab, struct segment_table_entry **ent,
const char *name)
{
for (uint32_t i = 0; i < segtab->len; i++) {
const char *segname = segtab->entries[i].name;
if (strcmp(name, segname) != 0)
continue;
*ent = &segtab->entries[i];
return M_SUCCESS;
}
return M_ERROR;
}
int segtab_ent_init(struct segment_table_entry *ent)
{
ent->len = 0;
ent->size = SEGTAB_INIT_SIZE;
ent->parts = malloc(sizeof(struct segment *) *
SEGTAB_INIT_SIZE);
if (ent->parts == NULL) {
PERROR("cannot alloc");
return M_ERROR;
}
return M_SUCCESS;
}
void segtab_ent_free(struct segment_table_entry *ent)
{
free(ent->parts);
}
int segtab_ent_push(struct segment_table_entry *ent, struct segment *seg)
{
if (ent->len >= ent->size) {
uint32_t size = ent->size * 2;
void *new = realloc(ent->parts,
sizeof(struct segment *) * size);
if (new == NULL) {
PERROR("cannot relloc");
return M_ERROR;
}
ent->size = size;
ent->parts = new;
}
if (ent->len > 0) {
struct segment *first = ent->parts[0];
if (first->align != seg->align) {
ERROR("segment '%s' doest not have matching alignment",
ent->name);
}
if (first->read != seg->read ||
first->write != seg->write ||
first->execute != seg->execute) {
ERROR("segment '%s' doest not have matching RWX",
ent->name);
}
} else {
ent->off = seg->new_off;
ent->vaddr = seg->new_vaddr;
}
ent->parts[ent->len++] = seg;
return M_SUCCESS;
}
uint32_t segtab_ent_size(struct segment_table_entry *ent)
{
uint32_t size = 0;
for (uint32_t i = 0; i < ent->len; i++) {
size += ent->parts[i]->size;
}
return size;
}
|