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
|
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <libelfu/libelfu.h>
static void modelToPhdrs(ElfuElf *me, Elf *e)
{
ElfuPhdr *mp;
size_t i;
/* Count PHDRs */
i = 0;
CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
i++;
}
if (!gelf_newphdr(e, i)) {
ELFU_WARNELF("gelf_newphdr");
}
/* Copy PHDRs */
i = 0;
CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
if (!gelf_update_phdr (e, i, &mp->phdr)) {
ELFU_WARNELF("gelf_update_phdr");
}
i++;
}
}
static void* modelToSection(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2)
{
(void) me;
(void) aux2;
Elf *e = (Elf*)aux1;
Elf_Scn *scnOut;
scnOut = elf_newscn(e);
if (!scnOut) {
ELFU_WARNELF("elf_newscn");
return (void*)-1;
}
/* SHDR */
if (ms->linkptr) {
ms->shdr.sh_link = elfu_mScnIndex(me, ms->linkptr);
}
if (ms->infoptr) {
ms->shdr.sh_info = elfu_mScnIndex(me, ms->infoptr);
}
if (!gelf_update_shdr(scnOut, &ms->shdr)) {
ELFU_WARNELF("gelf_update_shdr");
}
/* Data */
if (ms->data.d_buf) {
Elf_Data *dataOut = elf_newdata(scnOut);
if (!dataOut) {
ELFU_WARNELF("elf_newdata");
}
dataOut->d_align = ms->data.d_align;
dataOut->d_buf = ms->data.d_buf;
dataOut->d_off = ms->data.d_off;
dataOut->d_type = ms->data.d_type;
dataOut->d_size = ms->data.d_size;
dataOut->d_version = ms->data.d_version;
}
return NULL;
}
void elfu_mToElf(ElfuElf *me, Elf *e)
{
if (me->symtab) {
elfu_mSymtabFlatten(me);
}
/* We control the ELF file's layout now. */
/* tired's libelf also offers ELF_F_LAYOUT_OVERLAP for overlapping sections,
* but we don't want that since we filtered it out in the reading stage
* already. It would be too mind-blowing to handle the dependencies between
* the PHDRs and sections then... */
elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT);
/* EHDR */
if (!gelf_newehdr(e, me->elfclass)) {
ELFU_WARNELF("gelf_newehdr");
}
if (me->shstrtab) {
me->ehdr.e_shstrndx = elfu_mScnIndex(me, me->shstrtab);
}
if (!gelf_update_ehdr(e, &me->ehdr)) {
ELFU_WARNELF("gelf_update_ehdr");
}
/* Sections */
elfu_mScnForall(me, modelToSection, e, NULL);
/* PHDRs */
modelToPhdrs(me, e);
elf_flagelf(e, ELF_C_SET, ELF_F_DIRTY);
}
|