packaging: update version to 1.4.0
[platform/upstream/oprofile.git] / opjitconv / create_bfd.c
1 /**
2  * @file create_bfd.c
3  * Routine to handle elf file creation
4  *
5  * @remark Copyright 2007 OProfile authors
6  * @remark Read the file COPYING
7  *
8  * @author Jens Wilke
9  * @Modifications Maynard Johnson
10  * @Modifications Philippe Elie
11  * @Modifications Daniel Hansel
12  *
13  * Copyright IBM Corporation 2007
14  *
15  */
16
17 #include "opjitconv.h"
18 #include "op_libiberty.h"
19 #include "op_bfd_wrappers.h"
20
21 #include <bfd.h>
22 #include <assert.h>
23 #include <stdint.h>
24 #include <stdio.h>
25
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)
29 {
30         int rc = OP_JIT_CONV_OK;
31         u32 i;
32         int r;
33         struct jitentry const * e;
34         asymbol * s;
35         asection * section = NULL;
36
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;
41                 goto out;
42         }
43         
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];
51                 if (e->section)
52                         section = e->section;
53                 s = bfd_make_empty_symbol(cur_bfd);
54                 if (!s) {
55                         bfd_perror("bfd_make_empty_symbol");
56                         rc = OP_JIT_CONV_FAIL;
57                         goto out;
58                 }
59                 s->name = e->symbol_name;
60                 s->section = section;
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);
65                 syms[i] = s;
66         }
67         r = bfd_set_symtab(cur_bfd, syms, entry_count);
68         if (r == FALSE) {
69                 bfd_perror("bfd_set_symtab");
70                 rc = OP_JIT_CONV_FAIL;
71         }
72 out:
73         return rc;
74 }
75
76 /*
77  * create a new section.
78  */
79 asection * create_section(bfd * abfd, char const * section_name,
80                           size_t size, bfd_vma vma, flagword flags)
81 {
82         asection * section;
83
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");
88                 goto error;
89         }
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");
93                 goto error;
94         }
95         if (op_bfd_set_section_flags(abfd, section, flags) == FALSE) {
96                 bfd_perror("bfd_set_section_flags");
97                 goto error;
98         }
99         return section;
100 error:
101         return NULL;
102 }
103
104
105 /* create a .text section. end_idx: index last jitentry (inclusive!)  */
106 static int create_text_section(int start_idx, int end_idx)
107 {
108         int rc = OP_JIT_CONV_OK;
109
110         asection * section;
111         char const * section_name;
112         int idx = start_idx;
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;
118
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);
122
123         section = create_section(cur_bfd, section_name, size, vma_start,
124                SEC_ALLOC|SEC_LOAD|SEC_READONLY|SEC_CODE|SEC_HAS_CONTENTS);
125         if (section)
126                 entries_address_ascending[start_idx]->section = section;
127         else
128                 rc = OP_JIT_CONV_FAIL;
129
130         return rc;
131 }
132
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)
136 {
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;
140         }
141         return OP_JIT_CONV_OK;
142 }
143
144 /*
145  * Copy all code of the functions that are within start_idx and end_idx to 
146  * the section.
147  */
148 static int fill_text_section_content(asection * section, int start_idx,
149                                      int end_idx)
150 {
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;
155         int i;
156
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",
162                            section->name, i,
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.
169                  */
170                 if (e->code) {
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)
175                                 break;
176                 }
177         }
178         return rc;
179 }
180
181
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.
184  */
185 int partition_sections(void)
186 {
187         int rc = OP_JIT_CONV_OK;
188         u32 i, j;
189         struct jitentry const * pred;
190         struct jitentry const * entry;
191         unsigned long long end_addr;
192
193         // i: start index of the section
194         i = 0;
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)
204                                 goto out;
205                         i = j;
206                 }
207         }
208         // this holds always if we have at least one jitentry
209         if (i < entry_count)
210                 rc = create_text_section(i, entry_count - 1);
211 out:
212         return rc;
213 }
214
215
216 /* Fill the code content into the sections created by partition_sections() */
217 int fill_sections(void)
218 {
219         int rc = OP_JIT_CONV_OK;
220         u32 i, j;
221         asection * section;
222
223         rc = fill_symtab();
224         if (rc == OP_JIT_CONV_FAIL)
225                 goto out;
226
227         verbprintf(debug, "opjitconv: fill_sections\n");
228         i = 0;
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,
233                                                        j - 1);
234                         if (rc == OP_JIT_CONV_FAIL)
235                                 goto out;
236                         i = j;
237                 }
238         }
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,
243                                                i, entry_count - 1);
244         }
245 out:
246         return rc;
247 }
248
249
250 /* create the elf file */
251 bfd * open_elf(char const * filename)
252 {
253         bfd * abfd;
254
255         abfd = bfd_openw(filename, dump_bfd_target_name);
256         if (!abfd) {
257                 bfd_perror("bfd_openw");
258                 goto error1;
259         }
260         if (bfd_set_format(abfd, bfd_object) == FALSE) {
261                 bfd_perror("bfd_set_format");
262                 goto error;
263         }
264         if (bfd_set_arch_mach(abfd, dump_bfd_arch, dump_bfd_mach) == FALSE) {
265                 bfd_perror("bfd_set_arch_mach");
266                 goto error;
267         }
268         return abfd;
269 error:
270         bfd_close(abfd);
271 error1:
272         return NULL;
273 }