3 * Routine to handle elf file creation
5 * @remark Copyright 2007 OProfile authors
6 * @remark Read the file COPYING
9 * @Modifications Maynard Johnson
10 * @Modifications Philippe Elie
11 * @Modifications Daniel Hansel
13 * Copyright IBM Corporation 2007
17 #include "opjitconv.h"
18 #include "op_libiberty.h"
19 #include "op_bfd_wrappers.h"
26 /* Create the symbols and fill the syms array for all functions
27 * from start_idx to end_idx pointing into entries_address_ascending array */
28 static int fill_symtab(void)
30 int rc = OP_JIT_CONV_OK;
33 struct jitentry const * e;
35 asection * section = NULL;
37 /* Check for valid value of entry_count to avoid integer overflow. */
38 if (entry_count > UINT32_MAX - 1) {
39 bfd_perror("invalid entry_count value");
40 rc = OP_JIT_CONV_FAIL;
44 syms = xmalloc(sizeof(asymbol *) * (entry_count+1));
45 syms[entry_count] = NULL;
46 assert(entries_address_ascending[0]->section);
47 // Do this to silence Coverity
48 section = entries_address_ascending[0]->section;
49 for (i = 0; i < entry_count; i++) {
50 e = entries_address_ascending[i];
53 s = bfd_make_empty_symbol(cur_bfd);
55 bfd_perror("bfd_make_empty_symbol");
56 rc = OP_JIT_CONV_FAIL;
59 s->name = e->symbol_name;
61 s->flags = BSF_GLOBAL | BSF_FUNCTION;
62 s->value = e->vma - section->vma;
63 verbprintf(debug,"add sym: name=%s, value=%llx\n", s->name,
64 (unsigned long long)s->value);
67 r = bfd_set_symtab(cur_bfd, syms, entry_count);
69 bfd_perror("bfd_set_symtab");
70 rc = OP_JIT_CONV_FAIL;
77 * create a new section.
79 asection * create_section(bfd * abfd, char const * section_name,
80 size_t size, bfd_vma vma, flagword flags)
84 verbprintf(debug, "create_section() %s\n", section_name);
85 section = bfd_make_section(abfd, section_name);
86 if (section == NULL) {
87 bfd_perror("bfd_make_section");
90 op_bfd_set_section_vma(abfd, section, vma);
91 if (op_bfd_set_section_size(abfd, section, size) == FALSE) {
92 bfd_perror("bfd_set_section_size");
95 if (op_bfd_set_section_flags(abfd, section, flags) == FALSE) {
96 bfd_perror("bfd_set_section_flags");
105 /* create a .text section. end_idx: index last jitentry (inclusive!) */
106 static int create_text_section(int start_idx, int end_idx)
108 int rc = OP_JIT_CONV_OK;
111 char const * section_name;
113 unsigned long long vma_start =
114 entries_address_ascending[start_idx]->vma;
115 struct jitentry * ee = entries_address_ascending[end_idx];
116 unsigned long long vma_end = ee->vma + ee->code_size;
117 int size = vma_end - vma_start;
119 section_name = bfd_get_unique_section_name(cur_bfd, ".text", &idx);
120 verbprintf(debug, "section idx=%i, name=%s, vma_start=%llx, size=%i\n",
121 idx, section_name, vma_start, size);
123 section = create_section(cur_bfd, section_name, size, vma_start,
124 SEC_ALLOC|SEC_LOAD|SEC_READONLY|SEC_CODE|SEC_HAS_CONTENTS);
126 entries_address_ascending[start_idx]->section = section;
128 rc = OP_JIT_CONV_FAIL;
133 /* fill a section contents at a given offset from the start of the section */
134 int fill_section_content(bfd * abfd, asection * section,
135 void const * b, file_ptr offset, size_t sz)
137 if (bfd_set_section_contents(abfd, section, b, offset, sz) == FALSE) {
138 bfd_perror("bfd_set_section_contents");
139 return OP_JIT_CONV_FAIL;
141 return OP_JIT_CONV_OK;
145 * Copy all code of the functions that are within start_idx and end_idx to
148 static int fill_text_section_content(asection * section, int start_idx,
151 int rc = OP_JIT_CONV_OK;
152 unsigned long long vma_start =
153 entries_address_ascending[start_idx]->vma;
154 struct jitentry const * e;
157 for (i = start_idx; i <= end_idx; i++) {
158 e = entries_address_ascending[i];
159 verbprintf(debug, "section = %s, i = %i, code = %llx,"
160 " vma = %llx, offset = %llx,"
161 "size = %i, name = %s\n",
163 (unsigned long long) (uintptr_t) e->code,
164 e->vma, e->vma - vma_start,
165 e->code_size, e->symbol_name);
166 /* the right part that is created by split_entry may
167 * have no code; also, the agent may have passed NULL
168 * for the code location.
171 rc = fill_section_content(cur_bfd, section,
172 e->code, (file_ptr) (e->vma - vma_start),
173 (bfd_size_type)e->code_size);
174 if (rc != OP_JIT_CONV_OK)
182 /* Walk over the symbols sorted by address and create ELF sections. Whenever we
183 * have a gap greater or equal to 4096 make a new section.
185 int partition_sections(void)
187 int rc = OP_JIT_CONV_OK;
189 struct jitentry const * pred;
190 struct jitentry const * entry;
191 unsigned long long end_addr;
193 // i: start index of the section
195 for (j = 1; j < entry_count; j++) {
196 entry = entries_address_ascending[j];
197 pred = entries_address_ascending[j - 1];
198 end_addr = pred->vma + pred->code_size;
199 // calculate gap between code, if it is more than one page
200 // create an additional section
201 if ((entry->vma - end_addr) >= 4096) {
202 rc = create_text_section(i, j - 1);
203 if (rc == OP_JIT_CONV_FAIL)
208 // this holds always if we have at least one jitentry
210 rc = create_text_section(i, entry_count - 1);
216 /* Fill the code content into the sections created by partition_sections() */
217 int fill_sections(void)
219 int rc = OP_JIT_CONV_OK;
224 if (rc == OP_JIT_CONV_FAIL)
227 verbprintf(debug, "opjitconv: fill_sections\n");
229 for (j = 1; j < entry_count; j++) {
230 if (entries_address_ascending[j]->section) {
231 section = entries_address_ascending[i]->section;
232 rc = fill_text_section_content(section, i,
234 if (rc == OP_JIT_CONV_FAIL)
239 // this holds always if we have at least one jitentry
240 if (i < entry_count) {
241 section = entries_address_ascending[i]->section;
242 rc = fill_text_section_content(section,
250 /* create the elf file */
251 bfd * open_elf(char const * filename)
255 abfd = bfd_openw(filename, dump_bfd_target_name);
257 bfd_perror("bfd_openw");
260 if (bfd_set_format(abfd, bfd_object) == FALSE) {
261 bfd_perror("bfd_set_format");
264 if (bfd_set_arch_mach(abfd, dump_bfd_arch, dump_bfd_mach) == FALSE) {
265 bfd_perror("bfd_set_arch_mach");