ruby-static-tracing 0.0.12 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/ext/ruby-static-tracing/lib/deps-extconf.rb +1 -1
  3. data/ext/ruby-static-tracing/lib/libstapsdt/Makefile +76 -0
  4. data/ext/ruby-static-tracing/lib/libstapsdt/example/demo.c +42 -0
  5. data/ext/ruby-static-tracing/lib/libstapsdt/src/asm/libstapsdt-x86_64.s +14 -0
  6. data/ext/ruby-static-tracing/lib/libstapsdt/src/dynamic-symbols.c +41 -0
  7. data/ext/ruby-static-tracing/lib/libstapsdt/src/dynamic-symbols.h +34 -0
  8. data/ext/ruby-static-tracing/lib/libstapsdt/src/errors.c +30 -0
  9. data/ext/ruby-static-tracing/lib/libstapsdt/src/errors.h +8 -0
  10. data/ext/ruby-static-tracing/lib/libstapsdt/src/hash-table.c +27 -0
  11. data/ext/ruby-static-tracing/lib/libstapsdt/src/hash-table.h +3 -0
  12. data/ext/ruby-static-tracing/lib/libstapsdt/src/libstapsdt.c +258 -0
  13. data/ext/ruby-static-tracing/lib/libstapsdt/src/libstapsdt.h +67 -0
  14. data/ext/ruby-static-tracing/lib/libstapsdt/src/sdtnote.c +176 -0
  15. data/ext/ruby-static-tracing/lib/libstapsdt/src/sdtnote.h +46 -0
  16. data/ext/ruby-static-tracing/lib/libstapsdt/src/section.c +30 -0
  17. data/ext/ruby-static-tracing/lib/libstapsdt/src/section.h +21 -0
  18. data/ext/ruby-static-tracing/lib/libstapsdt/src/shared-lib.c +563 -0
  19. data/ext/ruby-static-tracing/lib/libstapsdt/src/shared-lib.h +46 -0
  20. data/ext/ruby-static-tracing/lib/libstapsdt/src/string-table.c +67 -0
  21. data/ext/ruby-static-tracing/lib/libstapsdt/src/string-table.h +28 -0
  22. data/ext/ruby-static-tracing/lib/libstapsdt/src/util.c +12 -0
  23. data/ext/ruby-static-tracing/lib/libstapsdt/src/util.h +6 -0
  24. data/ext/ruby-static-tracing/lib/libstapsdt/tests/test-errors.c +77 -0
  25. data/ext/ruby-static-tracing/lib/libstapsdt/tests/test-memory-leaks.c +25 -0
  26. data/ext/ruby-static-tracing/lib/libusdt/Makefile +168 -0
  27. data/ext/ruby-static-tracing/lib/libusdt/test_mem_usage.c +77 -0
  28. data/ext/ruby-static-tracing/lib/libusdt/test_usdt.c +87 -0
  29. data/ext/ruby-static-tracing/lib/libusdt/usdt.c +321 -0
  30. data/ext/ruby-static-tracing/lib/libusdt/usdt.h +65 -0
  31. data/ext/ruby-static-tracing/lib/libusdt/usdt_dof.c +126 -0
  32. data/ext/ruby-static-tracing/lib/libusdt/usdt_dof_file.c +290 -0
  33. data/ext/ruby-static-tracing/lib/libusdt/usdt_dof_sections.c +180 -0
  34. data/ext/ruby-static-tracing/lib/libusdt/usdt_internal.h +107 -0
  35. data/ext/ruby-static-tracing/lib/libusdt/usdt_probe.c +133 -0
  36. data/ext/ruby-static-tracing/lib/libusdt/usdt_tracepoints_i386.s +69 -0
  37. data/ext/ruby-static-tracing/lib/libusdt/usdt_tracepoints_x86_64.s +123 -0
  38. data/lib/ruby-static-tracing/version.rb +1 -1
  39. metadata +38 -2
@@ -0,0 +1,67 @@
1
+ #ifndef _LIBSTAPSDT_H
2
+ #define _LIBSTAPSDT_H
3
+ #define MAX_ARGUMENTS 6
4
+
5
+ typedef enum {
6
+ noError = -1,
7
+ elfCreationError = 0,
8
+ tmpCreationError = 1,
9
+ sharedLibraryOpenError = 2,
10
+ symbolLoadingError = 3,
11
+ sharedLibraryCloseError = 4,
12
+ } SDTError_t;
13
+
14
+ typedef enum {
15
+ noarg = 0,
16
+ uint8 = 1,
17
+ int8 = -1,
18
+ uint16 = 2,
19
+ int16 = -2,
20
+ uint32 = 4,
21
+ int32 = -4,
22
+ uint64 = 8,
23
+ int64 = -8,
24
+ } ArgType_t;
25
+
26
+ struct SDTProvider;
27
+
28
+ typedef struct SDTProbe {
29
+ char *name;
30
+ ArgType_t argFmt[MAX_ARGUMENTS];
31
+ void *_fire;
32
+ struct SDTProvider *provider;
33
+ int argCount;
34
+ } SDTProbe_t;
35
+
36
+ typedef struct SDTProbeList_ {
37
+ SDTProbe_t probe;
38
+ struct SDTProbeList_ *next;
39
+ } SDTProbeList_t;
40
+
41
+ typedef struct SDTProvider {
42
+ char *name;
43
+ SDTProbeList_t *probes;
44
+ SDTError_t errno;
45
+ char *error;
46
+
47
+ // private
48
+ void *_handle;
49
+ char *_filename;
50
+ int _memfd;
51
+ } SDTProvider_t;
52
+
53
+ SDTProvider_t *providerInit(const char *name);
54
+
55
+ SDTProbe_t *providerAddProbe(SDTProvider_t *provider, const char *name, int argCount, ...);
56
+
57
+ int providerLoad(SDTProvider_t *provider);
58
+
59
+ int providerUnload(SDTProvider_t *provider);
60
+
61
+ void providerDestroy(SDTProvider_t *provider);
62
+
63
+ void probeFire(SDTProbe_t *probe, ...);
64
+
65
+ int probeIsEnabled(SDTProbe_t *probe);
66
+
67
+ #endif
@@ -0,0 +1,176 @@
1
+ #include <stdlib.h>
2
+ #include <stdio.h>
3
+ #include <string.h>
4
+
5
+ #include "sdtnote.h"
6
+ #include "util.h"
7
+
8
+
9
+ // TODO (mmarchini) add other architectures (this only works for x86_64)
10
+ char *regMap(int idx) {
11
+ switch (idx) {
12
+ case 0:
13
+ return "rdi";
14
+ break;
15
+ case 1:
16
+ return "rsi";
17
+ break;
18
+ case 2:
19
+ return "rdx";
20
+ break;
21
+ case 3:
22
+ return "rcx";
23
+ break;
24
+ case 4:
25
+ return "r8";
26
+ break;
27
+ case 5:
28
+ return "r9";
29
+ break;
30
+ default:
31
+ return NULL;
32
+ }
33
+ }
34
+
35
+ size_t sdtNoteSize(SDTNote *sdt) {
36
+ size_t size = 0;
37
+ size += sizeof(sdt->header);
38
+ size += sdt->header.n_namesz;
39
+ size += sdt->header.n_descsz;
40
+
41
+ size = roundUp(size, 4);
42
+
43
+ return size;
44
+ }
45
+
46
+ SDTNote *sdtNoteInit(SDTProbe_t *probe) {
47
+ char buf[100];
48
+ SDTNote *sdt = calloc(sizeof(SDTNote), 1);
49
+ size_t descsz = 0, providersz = strlen(probe->provider->name) + 1,
50
+ probesz = strlen(probe->name) + 1;
51
+ sdt->header.n_type = NT_STAPSDT;
52
+ sdt->header.n_namesz = sizeof(NT_STAPSDT_NAME);
53
+
54
+ // TODO(matheus): should add pad if sizeof(NT_STAPSDT)%4 != 0
55
+ sdt->name = calloc(sizeof(NT_STAPSDT_NAME), 1);
56
+ strncpy(sdt->name, NT_STAPSDT_NAME, strlen(NT_STAPSDT_NAME) + 1);
57
+
58
+ sdt->content.probePC = -1;
59
+ descsz += sizeof(sdt->content.probePC);
60
+ sdt->content.base_addr = -1;
61
+ descsz += sizeof(sdt->content.base_addr);
62
+ sdt->content.sem_addr = 0;
63
+ descsz += sizeof(sdt->content.sem_addr);
64
+
65
+ sdt->content.provider = calloc(providersz, 1);
66
+ descsz += providersz;
67
+ strncpy(sdt->content.provider, probe->provider->name, providersz);
68
+
69
+ sdt->content.probe = calloc(probesz, 1);
70
+ descsz += probesz;
71
+ strncpy(sdt->content.probe, probe->name, probesz);
72
+
73
+ sdt->content.argFmt = calloc(sizeof(char), 1);
74
+ sdt->content.argFmt[0] = '\0';
75
+ for(int i=0; i < probe->argCount; i++) {
76
+ sprintf(buf, "%d@%%%s", probe->argFmt[i], regMap(i));
77
+
78
+
79
+ if(i==0) {
80
+ sdt->content.argFmt = realloc(sdt->content.argFmt, strlen(sdt->content.argFmt) + strlen(buf) + 1);
81
+ sprintf(sdt->content.argFmt, "%s", buf);
82
+ } else {
83
+ sdt->content.argFmt = realloc(sdt->content.argFmt, strlen(sdt->content.argFmt) + strlen(buf) + 2);
84
+ sprintf(&(sdt->content.argFmt[strlen(sdt->content.argFmt)]), " %s", buf);
85
+ }
86
+ }
87
+ descsz += strlen(sdt->content.argFmt) + 1;
88
+
89
+ sdt->header.n_descsz = descsz;
90
+
91
+ return sdt;
92
+ }
93
+
94
+ int sdtNoteToBuffer(SDTNote *sdt, char *buffer) {
95
+ int cur = 0;
96
+ size_t sdtSize = sdtNoteSize(sdt);
97
+
98
+ // Header
99
+ memcpy(&(buffer[cur]), &(sdt->header), sizeof(sdt->header));
100
+ cur += sizeof(sdt->header);
101
+
102
+ // Name
103
+ memcpy(&(buffer[cur]), sdt->name, sdt->header.n_namesz);
104
+ cur += sdt->header.n_namesz;
105
+
106
+ // Content
107
+ memcpy(&(buffer[cur]), &(sdt->content.probePC), sizeof(sdt->content.probePC));
108
+ cur += sizeof(sdt->content.probePC);
109
+
110
+ memcpy(&(buffer[cur]), &(sdt->content.base_addr),
111
+ sizeof(sdt->content.base_addr));
112
+ cur += sizeof(sdt->content.base_addr);
113
+
114
+ memcpy(&(buffer[cur]), &(sdt->content.sem_addr),
115
+ sizeof(sdt->content.sem_addr));
116
+ cur += sizeof(sdt->content.sem_addr);
117
+
118
+ memcpy(&(buffer[cur]), sdt->content.provider,
119
+ strlen(sdt->content.provider) + 1);
120
+ cur += strlen(sdt->content.provider) + 1;
121
+
122
+ memcpy(&(buffer[cur]), sdt->content.probe, strlen(sdt->content.probe) + 1);
123
+ cur += strlen(sdt->content.probe) + 1;
124
+
125
+ memcpy(&(buffer[cur]), sdt->content.argFmt, strlen(sdt->content.argFmt) + 1);
126
+ cur += strlen(sdt->content.argFmt) + 1;
127
+
128
+ if (cur < sdtSize) {
129
+ memset(&(buffer[cur]), 0, sdtSize - cur);
130
+ }
131
+
132
+ return sdtSize;
133
+ }
134
+
135
+ void sdtNoteFree(SDTNote *sdtNote) {
136
+ free(sdtNote->name);
137
+ free(sdtNote->content.provider);
138
+ free(sdtNote->content.probe);
139
+ free(sdtNote->content.argFmt);
140
+
141
+ free(sdtNote);
142
+ }
143
+
144
+ SDTNoteList_t *sdtNoteListAppend(SDTNoteList_t *list, SDTNote *note) {
145
+ SDTNoteList_t *newNode = calloc(sizeof(SDTNoteList_t), 1);
146
+ newNode->next = list;
147
+ newNode->note = note;
148
+
149
+ return newNode;
150
+ }
151
+
152
+ size_t sdtNoteListSize(SDTNoteList_t *list) {
153
+ size_t size = 0;
154
+ for(SDTNoteList_t *node=list; node!=NULL; node=node->next) {
155
+ size += sdtNoteSize(node->note);
156
+ }
157
+
158
+ return size;
159
+ }
160
+
161
+ size_t sdtNoteListToBuffer(SDTNoteList_t *list, char *buffer) {
162
+ size_t offset = 0;
163
+ for(SDTNoteList_t *node=list; node!=NULL; node=node->next) {
164
+ offset += sdtNoteToBuffer(node->note, &(buffer[offset]));
165
+ }
166
+ return offset;
167
+ }
168
+
169
+ void sdtNoteListFree(SDTNoteList_t *list) {
170
+ SDTNoteList_t *node, *next;
171
+ for(node=list; node!=NULL; node=next) {
172
+ sdtNoteFree(node->note);
173
+ next = node->next;
174
+ free(node);
175
+ }
176
+ }
@@ -0,0 +1,46 @@
1
+ #ifndef _SDT_NOTE_H
2
+ #define _SDT_NOTE_H
3
+
4
+ #include <libelf.h>
5
+ #include "libstapsdt.h"
6
+
7
+ #define NT_STAPSDT 3
8
+ #define NT_STAPSDT_NAME "stapsdt"
9
+
10
+ typedef struct SDTNote_ {
11
+ // Header
12
+ Elf64_Nhdr header;
13
+ // Note name
14
+ char *name;
15
+ struct {
16
+ // Note description
17
+ Elf64_Xword probePC;
18
+ Elf64_Xword base_addr;
19
+ Elf64_Xword sem_addr;
20
+ char *provider; // mainer
21
+ char *probe; //
22
+ char *argFmt; // \0
23
+ } content;
24
+ unsigned long long textSectionOffset;
25
+ } SDTNote;
26
+
27
+ typedef struct SDTNoteList_ {
28
+ SDTNote *note;
29
+ struct SDTNoteList_ *next;
30
+ } SDTNoteList_t;
31
+
32
+ size_t sdtNoteSize(SDTNote *sdt);
33
+
34
+ SDTNote *sdtNoteInit(SDTProbe_t *probe);
35
+
36
+ void sdtNoteFree(SDTNote *sdtNote);
37
+
38
+ SDTNoteList_t *sdtNoteListAppend(SDTNoteList_t *list, SDTNote *note);
39
+
40
+ size_t sdtNoteListSize(SDTNoteList_t *list);
41
+
42
+ size_t sdtNoteListToBuffer(SDTNoteList_t *list, char *buffer);
43
+
44
+ void sdtNoteListFree(SDTNoteList_t *list);
45
+
46
+ #endif
@@ -0,0 +1,30 @@
1
+ #include "section.h"
2
+
3
+ Section *sectionInit(Elf *e, StringTable *table, char *name) {
4
+ Section *section = calloc(sizeof(Section), 1);
5
+
6
+ section->string = stringTableAdd(table, name);
7
+
8
+ if ((section->scn = elf_newscn(e)) == NULL) {
9
+ free(section);
10
+ return NULL;
11
+ }
12
+
13
+ if ((section->data = elf_newdata(section->scn)) == NULL) {
14
+ free(section);
15
+ return NULL;
16
+ }
17
+
18
+ if ((section->shdr = elf64_getshdr(section->scn)) == NULL) {
19
+ free(section);
20
+ return NULL;
21
+ }
22
+
23
+ return section;
24
+ }
25
+
26
+
27
+ void sectionFree(Section *section) {
28
+ // Fields are just references, shouldn't be freed here
29
+ free(section);
30
+ }
@@ -0,0 +1,21 @@
1
+ #ifndef _SECTION_H
2
+ #define _SECTION_H
3
+
4
+ #include <libelf.h>
5
+
6
+ #include "string-table.h"
7
+
8
+ typedef struct {
9
+ Elf_Scn *scn;
10
+ Elf64_Shdr *shdr;
11
+ Elf_Data *data;
12
+ Elf64_Addr offset;
13
+
14
+ StringTableNode *string;
15
+ } Section;
16
+
17
+ Section *sectionInit(Elf *e, StringTable *table, char *name);
18
+
19
+ void sectionFree(Section *section);
20
+
21
+ #endif
@@ -0,0 +1,563 @@
1
+ #include <stdio.h>
2
+ #include "shared-lib.h"
3
+ #include "hash-table.h"
4
+
5
+ #define PHDR_ALIGN 0x200000
6
+
7
+ void _funcStart();
8
+ void _funcEnd();
9
+
10
+ uint32_t eh_frame[] = {0x0, 0x0};
11
+
12
+ Elf *createElf(int fd) {
13
+ Elf *e;
14
+
15
+ if (elf_version(EV_CURRENT) == EV_NONE) {
16
+ // TODO (mmarchini) error message
17
+ return NULL;
18
+ }
19
+
20
+ if ((e = elf_begin(fd, ELF_C_WRITE, NULL)) == NULL) {
21
+ // TODO (mmarchini) error message
22
+ return NULL;
23
+ }
24
+
25
+ return e;
26
+ }
27
+
28
+ int createElfStringTables(DynElf *dynElf) {
29
+ // FIXME (mmarchini) error handling
30
+ dynElf->stringTable = stringTableInit();
31
+ dynElf->dynamicString = stringTableInit();
32
+ dynElf->dynamicSymbols = dynamicSymbolTableInit(dynElf->dynamicString);
33
+ return 0;
34
+ }
35
+
36
+ Elf64_Ehdr *createElfHeader(Elf *elf) {
37
+ Elf64_Ehdr *ehdr;
38
+ if ((ehdr = elf64_newehdr(elf)) == NULL) {
39
+ // FIXME (mmarchini) properly free everything
40
+ return NULL;
41
+ }
42
+
43
+ ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
44
+ ehdr->e_type = ET_DYN;
45
+ ehdr->e_machine = EM_X86_64;
46
+ ehdr->e_version = EV_CURRENT;
47
+ ehdr->e_flags = 0;
48
+
49
+ return ehdr;
50
+ }
51
+
52
+ int createElfProgramHeaders(DynElf *dynElf) {
53
+ if ((dynElf->phdrLoad1 = elf64_newphdr(dynElf->elf, 4)) == NULL) {
54
+ // TODO (mmarchini) error message
55
+ // FIXME (mmarchini) properly free everything
56
+ return -1;
57
+ }
58
+
59
+ dynElf->phdrDyn = &dynElf->phdrLoad1[2];
60
+ dynElf->phdrLoad2 = &dynElf->phdrLoad1[1];
61
+ dynElf->phdrStack = &dynElf->phdrLoad1[3];
62
+
63
+ return 0;
64
+ }
65
+
66
+ int createElfSections(DynElf *dynElf) {
67
+ // FIXME (mmarchini) error message
68
+ dynElf->sections.shStrTab = sectionInit(dynElf->elf, dynElf->stringTable, ".shstrtab");
69
+ dynElf->sections.hash = sectionInit(dynElf->elf, dynElf->stringTable, ".hash");
70
+ dynElf->sections.dynSym = sectionInit(dynElf->elf, dynElf->stringTable, ".dynsym");
71
+ dynElf->sections.dynStr = sectionInit(dynElf->elf, dynElf->stringTable, ".dynstr");
72
+ dynElf->sections.text = sectionInit(dynElf->elf, dynElf->stringTable, ".text");
73
+ dynElf->sections.ehFrame = sectionInit(dynElf->elf, dynElf->stringTable, ".eh_frame");
74
+ dynElf->sections.dynamic = sectionInit(dynElf->elf, dynElf->stringTable, ".dynamic");
75
+ dynElf->sections.sdtBase = sectionInit(dynElf->elf, dynElf->stringTable, ".stapsdt.base");
76
+ dynElf->sections.sdtNote = sectionInit(dynElf->elf, dynElf->stringTable, ".note.stapsdt");
77
+
78
+ return 0;
79
+ }
80
+
81
+ void *createDynSymData(DynamicSymbolTable *table) {
82
+ size_t symbolsCount = (5 + table->count);
83
+ int i;
84
+ DynamicSymbolList *current;
85
+ Elf64_Sym *dynsyms = calloc(sizeof(Elf64_Sym), (5 + table->count));
86
+
87
+ for (i = 0; i < symbolsCount; i++) {
88
+ dynsyms[i].st_name = 0;
89
+ dynsyms[i].st_info = 0;
90
+ dynsyms[i].st_other = 0;
91
+ dynsyms[i].st_shndx = 0;
92
+ dynsyms[i].st_value = 0;
93
+ dynsyms[i].st_size = 0;
94
+ }
95
+
96
+ dynsyms[1].st_info = ELF64_ST_INFO(STB_LOCAL, STT_SECTION);
97
+
98
+ current = table->symbols;
99
+ for (i = 0; i < table->count; i++) {
100
+ dynsyms[i + 2].st_name = current->symbol.string->index;
101
+ dynsyms[i + 2].st_info = ELF64_ST_INFO(STB_GLOBAL, STT_NOTYPE);
102
+ current = current->next;
103
+ }
104
+ i -= 1;
105
+
106
+ dynsyms[i + 3].st_name = table->bssStart.string->index;
107
+ dynsyms[i + 3].st_info = ELF64_ST_INFO(STB_GLOBAL, STT_NOTYPE);
108
+
109
+ dynsyms[i + 4].st_name = table->eData.string->index;
110
+ dynsyms[i + 4].st_info = ELF64_ST_INFO(STB_GLOBAL, STT_NOTYPE);
111
+
112
+ dynsyms[i + 5].st_name = table->end.string->index;
113
+ dynsyms[i + 5].st_info = ELF64_ST_INFO(STB_GLOBAL, STT_NOTYPE);
114
+
115
+ return dynsyms;
116
+ }
117
+
118
+ // TODO(matheus): dynamic strings creation
119
+ void *createDynamicData() {
120
+ Elf64_Dyn *dyns = calloc(sizeof(Elf64_Dyn), 11);
121
+
122
+ for (int i = 0; i < 11; i++) {
123
+ dyns[i].d_tag = DT_NULL;
124
+ }
125
+
126
+ dyns[0].d_tag = DT_HASH;
127
+ dyns[1].d_tag = DT_STRTAB;
128
+ dyns[2].d_tag = DT_SYMTAB;
129
+ dyns[3].d_tag = DT_STRSZ;
130
+
131
+ return dyns;
132
+ }
133
+
134
+ DynElf *dynElfInit(int fd) {
135
+ DynElf *dynElf = (DynElf *)calloc(sizeof(DynElf), 1);
136
+ dynElf->sdtNotes = NULL;
137
+ dynElf->sdtNotesCount = 0;
138
+
139
+ if(createElfStringTables(dynElf) == -1) {
140
+ // TODO (mmarchini) error message
141
+ // FIXME (mmarchini) properly free everything
142
+ free(dynElf);
143
+ return NULL;
144
+ }
145
+
146
+ dynElf->elf = createElf(fd);
147
+
148
+ if ((dynElf->ehdr = createElfHeader(dynElf->elf)) == NULL) {
149
+ // TODO (mmarchini) error message
150
+ // FIXME (mmarchini) properly free everything
151
+ free(dynElf);
152
+ return NULL;
153
+ }
154
+
155
+ if(createElfProgramHeaders(dynElf) == -1) {
156
+ // TODO (mmarchini) error message
157
+ // FIXME (mmarchini) properly free everything
158
+ free(dynElf);
159
+ return NULL;
160
+ }
161
+
162
+ if(createElfSections(dynElf) == -1) {
163
+ // TODO (mmarchini) error message
164
+ // FIXME (mmarchini) properly free everything
165
+ free(dynElf);
166
+ return NULL;
167
+ }
168
+
169
+ return dynElf;
170
+ }
171
+
172
+ int dynElfAddProbe(DynElf *dynElf, SDTProbe_t *probe) {
173
+ dynElf->sdtNotes = sdtNoteListAppend(dynElf->sdtNotes, sdtNoteInit(probe));
174
+ dynamicSymbolTableAdd(dynElf->dynamicSymbols, probe->name);
175
+ dynElf->sdtNotesCount++;
176
+
177
+ return 0;
178
+ }
179
+
180
+ size_t prepareTextData(DynElf *dynElf, char **textData) {
181
+ size_t funcSize = (unsigned long long)_funcEnd - (unsigned long long)_funcStart;
182
+ unsigned long long offset=0;
183
+ *textData = calloc(funcSize, dynElf->sdtNotesCount);
184
+
185
+ for(SDTNoteList_t *node=dynElf->sdtNotes; node!=NULL; node=node->next) {
186
+ node->note->textSectionOffset = offset;
187
+ memcpy(&((*textData)[offset]), _funcStart, funcSize);
188
+ offset += funcSize;
189
+ }
190
+
191
+ return offset;
192
+ }
193
+
194
+ // TODO (mmarchini) refactor (no idea how)
195
+ int dynElfSave(DynElf *dynElf) {
196
+ Elf64_Sym *dynSymData = createDynSymData(dynElf->dynamicSymbols);
197
+ Elf64_Dyn *dynamicData = createDynamicData();
198
+ void *sdtNoteData = calloc(sdtNoteListSize(dynElf->sdtNotes), 1);
199
+ void *stringTableData = stringTableToBuffer(dynElf->stringTable),
200
+ *dynamicStringData = stringTableToBuffer(dynElf->dynamicString);
201
+ void *textData = NULL;
202
+ uint32_t *hashTable;
203
+ size_t hashTableSize = hashTableFromSymbolTable(dynElf->dynamicSymbols, &hashTable);
204
+ int i;
205
+
206
+ // ----------------------------------------------------------------------- //
207
+ // Section: HASH
208
+
209
+ dynElf->sections.hash->data->d_align = 8;
210
+ dynElf->sections.hash->data->d_off = 0LL;
211
+ dynElf->sections.hash->data->d_buf = hashTable;
212
+ dynElf->sections.hash->data->d_type = ELF_T_XWORD;
213
+ dynElf->sections.hash->data->d_size = hashTableSize;
214
+ dynElf->sections.hash->data->d_version = EV_CURRENT;
215
+
216
+ dynElf->sections.hash->shdr->sh_name = dynElf->sections.hash->string->index;
217
+ dynElf->sections.hash->shdr->sh_type = SHT_HASH;
218
+ dynElf->sections.hash->shdr->sh_flags = SHF_ALLOC;
219
+
220
+ // ----------------------------------------------------------------------- //
221
+ // Section: Dynsym
222
+
223
+ dynElf->sections.dynSym->data->d_align = 8;
224
+ dynElf->sections.dynSym->data->d_off = 0LL;
225
+ dynElf->sections.dynSym->data->d_buf = dynSymData;
226
+ dynElf->sections.dynSym->data->d_type = ELF_T_XWORD;
227
+ dynElf->sections.dynSym->data->d_size = sizeof(Elf64_Sym) * ((5 + dynElf->dynamicSymbols->count));
228
+ dynElf->sections.dynSym->data->d_version = EV_CURRENT;
229
+
230
+ dynElf->sections.dynSym->shdr->sh_name = dynElf->sections.dynSym->string->index;
231
+ dynElf->sections.dynSym->shdr->sh_type = SHT_DYNSYM;
232
+ dynElf->sections.dynSym->shdr->sh_flags = SHF_ALLOC;
233
+ dynElf->sections.dynSym->shdr->sh_info = 2; // First non local symbol
234
+
235
+ dynElf->sections.hash->shdr->sh_link = elf_ndxscn(dynElf->sections.dynSym->scn);
236
+
237
+ // ----------------------------------------------------------------------- //
238
+ // Section: DYNSTR
239
+
240
+ dynElf->sections.dynStr->data->d_align = 1;
241
+ dynElf->sections.dynStr->data->d_off = 0LL;
242
+ dynElf->sections.dynStr->data->d_buf = dynamicStringData;
243
+
244
+ dynElf->sections.dynStr->data->d_type = ELF_T_BYTE;
245
+ dynElf->sections.dynStr->data->d_size = dynElf->dynamicString->size;
246
+ dynElf->sections.dynStr->data->d_version = EV_CURRENT;
247
+
248
+ dynElf->sections.dynStr->shdr->sh_name = dynElf->sections.dynStr->string->index;
249
+ dynElf->sections.dynStr->shdr->sh_type = SHT_STRTAB;
250
+ dynElf->sections.dynStr->shdr->sh_flags = SHF_ALLOC;
251
+
252
+ dynElf->sections.dynSym->shdr->sh_link = elf_ndxscn(dynElf->sections.dynStr->scn);
253
+
254
+ // ----------------------------------------------------------------------- //
255
+ // Section: TEXT
256
+
257
+ dynElf->sections.text->data->d_align = 16;
258
+ dynElf->sections.text->data->d_off = 0LL;
259
+ dynElf->sections.text->data->d_size = prepareTextData(dynElf, (char **) &textData);
260
+ dynElf->sections.text->data->d_buf = textData;
261
+ dynElf->sections.text->data->d_type = ELF_T_BYTE;
262
+ dynElf->sections.text->data->d_version = EV_CURRENT;
263
+
264
+ dynElf->sections.text->shdr->sh_name = dynElf->sections.text->string->index;
265
+ dynElf->sections.text->shdr->sh_type = SHT_PROGBITS;
266
+ dynElf->sections.text->shdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR;
267
+
268
+ // ----------------------------------------------------------------------- //
269
+ // Section: SDT BASE
270
+
271
+ dynElf->sections.sdtBase->data->d_align = 1;
272
+ dynElf->sections.sdtBase->data->d_off = 0LL;
273
+ dynElf->sections.sdtBase->data->d_buf = eh_frame;
274
+ dynElf->sections.sdtBase->data->d_type = ELF_T_BYTE;
275
+ dynElf->sections.sdtBase->data->d_size = 1;
276
+ dynElf->sections.sdtBase->data->d_version = EV_CURRENT;
277
+
278
+ dynElf->sections.sdtBase->shdr->sh_name = dynElf->sections.sdtBase->string->index;
279
+ dynElf->sections.sdtBase->shdr->sh_type = SHT_PROGBITS;
280
+ dynElf->sections.sdtBase->shdr->sh_flags = SHF_ALLOC;
281
+
282
+ // ----------------------------------------------------------------------- //
283
+ // Section: EH_FRAME
284
+
285
+ dynElf->sections.ehFrame->data->d_align = 8;
286
+ dynElf->sections.ehFrame->data->d_off = 0LL;
287
+ dynElf->sections.ehFrame->data->d_buf = eh_frame;
288
+ dynElf->sections.ehFrame->data->d_type = ELF_T_BYTE;
289
+ dynElf->sections.ehFrame->data->d_size = 0;
290
+ dynElf->sections.ehFrame->data->d_version = EV_CURRENT;
291
+
292
+ dynElf->sections.ehFrame->shdr->sh_name = dynElf->sections.ehFrame->string->index;
293
+ dynElf->sections.ehFrame->shdr->sh_type = SHT_PROGBITS;
294
+ dynElf->sections.ehFrame->shdr->sh_flags = SHF_ALLOC;
295
+
296
+ // ----------------------------------------------------------------------- //
297
+ // Section: DYNAMIC
298
+
299
+ dynElf->sections.dynamic->data->d_align = 8;
300
+ dynElf->sections.dynamic->data->d_off = 0LL;
301
+ dynElf->sections.dynamic->data->d_buf = dynamicData;
302
+ dynElf->sections.dynamic->data->d_type = ELF_T_BYTE;
303
+ dynElf->sections.dynamic->data->d_size = 11 * sizeof(Elf64_Dyn);
304
+ dynElf->sections.dynamic->data->d_version = EV_CURRENT;
305
+
306
+ dynElf->sections.dynamic->shdr->sh_name = dynElf->sections.dynamic->string->index;
307
+ dynElf->sections.dynamic->shdr->sh_type = SHT_DYNAMIC;
308
+ dynElf->sections.dynamic->shdr->sh_flags = SHF_WRITE | SHF_ALLOC;
309
+ dynElf->sections.dynamic->shdr->sh_link = elf_ndxscn(dynElf->sections.dynStr->scn);
310
+
311
+ // ----------------------------------------------------------------------- //
312
+ // Section: SDT_NOTE
313
+
314
+ dynElf->sections.sdtNote->data->d_align = 4;
315
+ dynElf->sections.sdtNote->data->d_off = 0LL;
316
+ dynElf->sections.sdtNote->data->d_buf = sdtNoteData;
317
+ dynElf->sections.sdtNote->data->d_type = ELF_T_NHDR;
318
+ dynElf->sections.sdtNote->data->d_size = sdtNoteListSize(dynElf->sdtNotes);
319
+ dynElf->sections.sdtNote->data->d_version = EV_CURRENT;
320
+
321
+ dynElf->sections.sdtNote->shdr->sh_name = dynElf->sections.sdtNote->string->index;
322
+ dynElf->sections.sdtNote->shdr->sh_type = SHT_NOTE;
323
+ dynElf->sections.sdtNote->shdr->sh_flags = 0;
324
+
325
+ // ----------------------------------------------------------------------- //
326
+ // Section: SHSTRTAB
327
+
328
+ dynElf->sections.shStrTab->data->d_align = 1;
329
+ dynElf->sections.shStrTab->data->d_off = 0LL;
330
+ dynElf->sections.shStrTab->data->d_buf = stringTableData;
331
+ dynElf->sections.shStrTab->data->d_type = ELF_T_BYTE;
332
+ dynElf->sections.shStrTab->data->d_size = dynElf->stringTable->size;
333
+ dynElf->sections.shStrTab->data->d_version = EV_CURRENT;
334
+
335
+ dynElf->sections.shStrTab->shdr->sh_name = dynElf->sections.shStrTab->string->index;
336
+ dynElf->sections.shStrTab->shdr->sh_type = SHT_STRTAB;
337
+ dynElf->sections.shStrTab->shdr->sh_flags = 0;
338
+
339
+ dynElf->ehdr->e_shstrndx = elf_ndxscn(dynElf->sections.shStrTab->scn);
340
+
341
+ // ----------------------------------------------------------------------- //
342
+
343
+ if (elf_update(dynElf->elf, ELF_C_NULL) < 0) {
344
+ return -1;
345
+ }
346
+
347
+ dynElf->sections.hash->shdr->sh_addr = dynElf->sections.hash->shdr->sh_offset;
348
+ dynElf->sections.hash->offset = dynElf->sections.hash->shdr->sh_offset;
349
+
350
+ // -- //
351
+
352
+ dynElf->sections.dynSym->shdr->sh_addr = dynElf->sections.dynSym->shdr->sh_offset;
353
+ dynElf->sections.dynSym->offset = dynElf->sections.dynSym->shdr->sh_offset;
354
+
355
+ // -- //
356
+
357
+ dynElf->sections.dynStr->shdr->sh_addr = dynElf->sections.dynStr->shdr->sh_offset;
358
+ dynElf->sections.dynStr->offset = dynElf->sections.dynStr->shdr->sh_offset;
359
+
360
+ // -- //
361
+
362
+ dynElf->sections.text->shdr->sh_addr = dynElf->sections.text->shdr->sh_offset;
363
+ dynElf->ehdr->e_entry = dynElf->sections.text->shdr->sh_addr;
364
+ dynElf->sections.text->offset = dynElf->sections.text->shdr->sh_offset;
365
+
366
+ // -- //
367
+
368
+ dynElf->sections.sdtBase->shdr->sh_addr = dynElf->sections.sdtBase->shdr->sh_offset;
369
+ dynElf->sections.sdtBase->offset = dynElf->sections.sdtBase->shdr->sh_offset;
370
+
371
+ // -- //
372
+
373
+ dynElf->sections.ehFrame->shdr->sh_addr = dynElf->sections.ehFrame->shdr->sh_offset;
374
+ dynElf->sections.ehFrame->offset = dynElf->sections.ehFrame->shdr->sh_offset;
375
+
376
+ // -- //
377
+
378
+ dynElf->sections.dynamic->shdr->sh_addr = PHDR_ALIGN + dynElf->sections.dynamic->shdr->sh_offset;
379
+ dynElf->sections.dynamic->offset = dynElf->sections.dynamic->shdr->sh_offset;
380
+
381
+ // -- //
382
+
383
+ dynElf->sections.sdtNote->shdr->sh_addr = dynElf->sections.sdtNote->shdr->sh_offset;
384
+ dynElf->sections.sdtNote->offset = dynElf->sections.sdtNote->shdr->sh_offset;
385
+
386
+ for(SDTNoteList_t *node=dynElf->sdtNotes; node != NULL; node = node->next) {
387
+ node->note->content.probePC = dynElf->sections.text->offset + node->note->textSectionOffset;
388
+ node->note->content.base_addr = dynElf->sections.sdtBase->offset;
389
+ }
390
+ sdtNoteListToBuffer(dynElf->sdtNotes, sdtNoteData);
391
+
392
+ // -- //
393
+
394
+ dynElf->sections.shStrTab->offset = dynElf->sections.shStrTab->shdr->sh_offset;
395
+
396
+ // -- //
397
+
398
+ // ----------------------------------------------------------------------- //
399
+
400
+ if (elf_update(dynElf->elf, ELF_C_NULL) < 0) {
401
+ return -1;
402
+ }
403
+
404
+ // ----------------------------------------------------------------------- //
405
+ // Fill PHDRs
406
+
407
+ // First LOAD PHDR
408
+
409
+ dynElf->phdrLoad1->p_type = PT_LOAD;
410
+ dynElf->phdrLoad1->p_flags = PF_X + PF_R;
411
+ dynElf->phdrLoad1->p_offset = 0;
412
+ dynElf->phdrLoad1->p_vaddr = 0;
413
+ dynElf->phdrLoad1->p_paddr = 0;
414
+ dynElf->phdrLoad1->p_filesz = dynElf->sections.ehFrame->offset;
415
+ dynElf->phdrLoad1->p_memsz = dynElf->sections.ehFrame->offset;
416
+ dynElf->phdrLoad1->p_align = PHDR_ALIGN;
417
+
418
+ // Second LOAD PHDR
419
+
420
+ dynElf->phdrLoad2->p_type = PT_LOAD;
421
+ dynElf->phdrLoad2->p_flags = PF_W + PF_R;
422
+ dynElf->phdrLoad2->p_offset = dynElf->sections.ehFrame->offset;
423
+ dynElf->phdrLoad2->p_vaddr = dynElf->sections.ehFrame->offset + PHDR_ALIGN;
424
+ dynElf->phdrLoad2->p_paddr = dynElf->sections.ehFrame->offset + PHDR_ALIGN;
425
+ dynElf->phdrLoad2->p_filesz = dynElf->sections.dynamic->data->d_size;
426
+ dynElf->phdrLoad2->p_memsz = dynElf->sections.dynamic->data->d_size;
427
+ dynElf->phdrLoad2->p_align = PHDR_ALIGN;
428
+
429
+ // Dynamic PHDR
430
+
431
+ dynElf->phdrDyn->p_type = PT_DYNAMIC;
432
+ dynElf->phdrDyn->p_flags = PF_W + PF_R;
433
+ dynElf->phdrDyn->p_offset = dynElf->sections.ehFrame->offset;
434
+ dynElf->phdrDyn->p_vaddr = dynElf->sections.ehFrame->offset + PHDR_ALIGN;
435
+ dynElf->phdrDyn->p_paddr = dynElf->sections.ehFrame->offset + PHDR_ALIGN;
436
+ dynElf->phdrDyn->p_filesz = dynElf->sections.dynamic->data->d_size;
437
+ dynElf->phdrDyn->p_memsz = dynElf->sections.dynamic->data->d_size;
438
+ dynElf->phdrDyn->p_align = 0x8; // XXX magic number?
439
+
440
+ // GNU_STACK PHDR
441
+ dynElf->phdrStack->p_type = PT_GNU_STACK;
442
+ dynElf->phdrStack->p_flags = PF_W + PF_R;
443
+ dynElf->phdrStack->p_offset = 0;
444
+ dynElf->phdrStack->p_vaddr = 0;
445
+ dynElf->phdrStack->p_paddr = 0;
446
+ dynElf->phdrStack->p_filesz = 0;
447
+ dynElf->phdrStack->p_memsz = 0;
448
+ dynElf->phdrStack->p_align = 0x10;
449
+
450
+ // Fix offsets DynSym
451
+ // ----------------------------------------------------------------------- //
452
+
453
+ dynSymData[0].st_value = 0;
454
+
455
+ dynSymData[1].st_value = dynElf->sections.text->offset;
456
+ dynSymData[1].st_shndx = elf_ndxscn(dynElf->sections.text->scn);
457
+
458
+
459
+ i=0;
460
+ for (SDTNoteList_t *node = dynElf->sdtNotes; node != NULL; node = node->next) {
461
+ dynSymData[i + 2].st_value = dynElf->sections.text->offset + node->note->textSectionOffset;
462
+ dynSymData[i + 2].st_shndx = elf_ndxscn(dynElf->sections.text->scn);
463
+ i++;
464
+ }
465
+ i -= 1;
466
+
467
+ dynSymData[i + 3].st_value = PHDR_ALIGN + dynElf->sections.shStrTab->offset;
468
+ dynSymData[i + 3].st_shndx = elf_ndxscn(dynElf->sections.dynamic->scn);
469
+
470
+ dynSymData[i + 4].st_value = PHDR_ALIGN + dynElf->sections.shStrTab->offset;
471
+ dynSymData[i + 4].st_shndx = elf_ndxscn(dynElf->sections.dynamic->scn);
472
+
473
+ dynSymData[i + 5].st_value = PHDR_ALIGN + dynElf->sections.shStrTab->offset;
474
+ dynSymData[i + 5].st_shndx = elf_ndxscn(dynElf->sections.dynamic->scn);
475
+
476
+ // Fix offsets Dynamic
477
+ // ----------------------------------------------------------------------- //
478
+
479
+ dynamicData[0].d_un.d_ptr = dynElf->sections.hash->offset;
480
+ dynamicData[1].d_un.d_ptr = dynElf->sections.dynStr->offset;
481
+ dynamicData[2].d_un.d_ptr = dynElf->sections.dynSym->offset;
482
+ dynamicData[3].d_un.d_val = dynElf->dynamicString->size;
483
+ dynamicData[4].d_un.d_val = sizeof(Elf64_Sym);
484
+
485
+ // ----------------------------------------------------------------------- //
486
+
487
+ elf_flagphdr(dynElf->elf, ELF_C_SET, ELF_F_DIRTY);
488
+
489
+ if (elf_update(dynElf->elf, ELF_C_WRITE) < 0) {
490
+ return -1;
491
+ }
492
+
493
+ free(textData);
494
+ free(dynSymData);
495
+ free(dynamicData);
496
+ free(sdtNoteData);
497
+ free(stringTableData);
498
+ free(dynamicStringData);
499
+ free(hashTable);
500
+ return 0;
501
+ }
502
+
503
+ void dynElfSectionsClose(SectionsList *sections) {
504
+ if(sections->hash != NULL) {
505
+ sectionFree(sections->hash);
506
+ }
507
+
508
+ if(sections->dynSym != NULL) {
509
+ sectionFree(sections->dynSym);
510
+ }
511
+
512
+ if(sections->dynStr != NULL) {
513
+ sectionFree(sections->dynStr);
514
+ }
515
+
516
+ if(sections->text != NULL) {
517
+ sectionFree(sections->text);
518
+ }
519
+
520
+ if(sections->sdtBase != NULL) {
521
+ sectionFree(sections->sdtBase);
522
+ }
523
+
524
+ if(sections->ehFrame != NULL) {
525
+ sectionFree(sections->ehFrame);
526
+ }
527
+
528
+ if(sections->dynamic != NULL) {
529
+ sectionFree(sections->dynamic);
530
+ }
531
+
532
+ if(sections->sdtNote != NULL) {
533
+ sectionFree(sections->sdtNote);
534
+ }
535
+
536
+ if(sections->shStrTab != NULL) {
537
+ sectionFree(sections->shStrTab);
538
+ }
539
+ }
540
+
541
+
542
+ void dynElfClose(DynElf *dynElf) {
543
+ if(dynElf->stringTable != NULL) {
544
+ stringTableFree(dynElf->stringTable);
545
+ }
546
+
547
+ if(dynElf->dynamicString != NULL) {
548
+ stringTableFree(dynElf->dynamicString);
549
+ }
550
+
551
+ if(dynElf->dynamicSymbols != NULL) {
552
+ dynamicSymbolTableFree(dynElf->dynamicSymbols);
553
+ }
554
+
555
+ if(dynElf->sdtNotes != NULL) {
556
+ sdtNoteListFree(dynElf->sdtNotes);
557
+ }
558
+
559
+ dynElfSectionsClose(&dynElf->sections);
560
+
561
+ (void)elf_end(dynElf->elf);
562
+ free(dynElf);
563
+ }