1/*
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#include "precompiled.hpp"
26
27#if !defined(_WINDOWS) && !defined(__APPLE__)
28
29#include <string.h>
30#include <stdio.h>
31#include <limits.h>
32#include <new>
33
34#include "memory/allocation.inline.hpp"
35#include "utilities/decoder.hpp"
36#include "utilities/elfFile.hpp"
37#include "utilities/elfFuncDescTable.hpp"
38#include "utilities/elfStringTable.hpp"
39#include "utilities/elfSymbolTable.hpp"
40
41
42ElfFile::ElfFile(const char* filepath) {
43  assert(filepath, "null file path");
44  memset(&m_elfHdr, 0, sizeof(m_elfHdr));
45  m_string_tables = NULL;
46  m_symbol_tables = NULL;
47  m_funcDesc_table = NULL;
48  m_next = NULL;
49  m_status = NullDecoder::no_error;
50
51  int len = strlen(filepath) + 1;
52  m_filepath = (const char*)os::malloc(len * sizeof(char), mtInternal);
53  if (m_filepath != NULL) {
54    strcpy((char*)m_filepath, filepath);
55    m_file = fopen(filepath, "r");
56    if (m_file != NULL) {
57      load_tables();
58    } else {
59      m_status = NullDecoder::file_not_found;
60    }
61  } else {
62    m_status = NullDecoder::out_of_memory;
63  }
64}
65
66ElfFile::~ElfFile() {
67  if (m_string_tables != NULL) {
68    delete m_string_tables;
69  }
70
71  if (m_symbol_tables != NULL) {
72    delete m_symbol_tables;
73  }
74
75  if (m_file != NULL) {
76    fclose(m_file);
77  }
78
79  if (m_filepath != NULL) {
80    os::free((void*)m_filepath);
81  }
82
83  if (m_next != NULL) {
84    delete m_next;
85  }
86};
87
88
89//Check elf header to ensure the file is valid.
90bool ElfFile::is_elf_file(Elf_Ehdr& hdr) {
91  return (ELFMAG0 == hdr.e_ident[EI_MAG0] &&
92      ELFMAG1 == hdr.e_ident[EI_MAG1] &&
93      ELFMAG2 == hdr.e_ident[EI_MAG2] &&
94      ELFMAG3 == hdr.e_ident[EI_MAG3] &&
95      ELFCLASSNONE != hdr.e_ident[EI_CLASS] &&
96      ELFDATANONE != hdr.e_ident[EI_DATA]);
97}
98
99bool ElfFile::load_tables() {
100  assert(m_file, "file not open");
101  assert(!NullDecoder::is_error(m_status), "already in error");
102
103  // read elf file header
104  if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) {
105    m_status = NullDecoder::file_invalid;
106    return false;
107  }
108
109  if (!is_elf_file(m_elfHdr)) {
110    m_status = NullDecoder::file_invalid;
111    return false;
112  }
113
114  // walk elf file's section headers, and load string tables
115  Elf_Shdr shdr;
116  if (!fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) {
117    if (NullDecoder::is_error(m_status)) return false;
118
119    for (int index = 0; index < m_elfHdr.e_shnum; index ++) {
120      if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) {
121        m_status = NullDecoder::file_invalid;
122        return false;
123      }
124      if (shdr.sh_type == SHT_STRTAB) {
125        // string tables
126        ElfStringTable* table = new (std::nothrow) ElfStringTable(m_file, shdr, index);
127        if (table == NULL) {
128          m_status = NullDecoder::out_of_memory;
129          return false;
130        }
131        add_string_table(table);
132      } else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
133        // symbol tables
134        ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(m_file, shdr);
135        if (table == NULL) {
136          m_status = NullDecoder::out_of_memory;
137          return false;
138        }
139        add_symbol_table(table);
140      }
141    }
142
143#if defined(PPC64) && !defined(ABI_ELFv2)
144    // Now read the .opd section wich contains the PPC64 function descriptor table.
145    // The .opd section is only available on PPC64 (see for example:
146    // http://refspecs.linuxfoundation.org/LSB_3.1.1/LSB-Core-PPC64/LSB-Core-PPC64/specialsections.html)
147    // so this code should do no harm on other platforms but because of performance reasons we only
148    // execute it on PPC64 platforms.
149    // Notice that we can only find the .opd section after we have successfully read in the string
150    // tables in the previous loop, because we need to query the name of each section which is
151    // contained in one of the string tables (i.e. the one with the index m_elfHdr.e_shstrndx).
152
153    // Reset the file pointer
154    if (fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) {
155      m_status = NullDecoder::file_invalid;
156      return false;
157    }
158    for (int index = 0; index < m_elfHdr.e_shnum; index ++) {
159      if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) {
160        m_status = NullDecoder::file_invalid;
161        return false;
162      }
163      if (m_elfHdr.e_shstrndx != SHN_UNDEF && shdr.sh_type == SHT_PROGBITS) {
164        ElfStringTable* string_table = get_string_table(m_elfHdr.e_shstrndx);
165        if (string_table == NULL) {
166          m_status = NullDecoder::file_invalid;
167          return false;
168        }
169        char buf[8]; // '8' is enough because we only want to read ".opd"
170        if (string_table->string_at(shdr.sh_name, buf, sizeof(buf)) && !strncmp(".opd", buf, 4)) {
171          m_funcDesc_table = new (std::nothrow) ElfFuncDescTable(m_file, shdr, index);
172          if (m_funcDesc_table == NULL) {
173            m_status = NullDecoder::out_of_memory;
174            return false;
175          }
176          break;
177        }
178      }
179    }
180#endif
181
182  }
183  return true;
184}
185
186bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) {
187  // something already went wrong, just give up
188  if (NullDecoder::is_error(m_status)) {
189    return false;
190  }
191  ElfSymbolTable* symbol_table = m_symbol_tables;
192  int string_table_index;
193  int pos_in_string_table;
194  int off = INT_MAX;
195  bool found_symbol = false;
196  while (symbol_table != NULL) {
197    if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off, m_funcDesc_table)) {
198      found_symbol = true;
199      break;
200    }
201    symbol_table = symbol_table->m_next;
202  }
203  if (!found_symbol) return false;
204
205  ElfStringTable* string_table = get_string_table(string_table_index);
206
207  if (string_table == NULL) {
208    m_status = NullDecoder::file_invalid;
209    return false;
210  }
211  if (offset) *offset = off;
212
213  return string_table->string_at(pos_in_string_table, buf, buflen);
214}
215
216
217void ElfFile::add_symbol_table(ElfSymbolTable* table) {
218  if (m_symbol_tables == NULL) {
219    m_symbol_tables = table;
220  } else {
221    table->m_next = m_symbol_tables;
222    m_symbol_tables = table;
223  }
224}
225
226void ElfFile::add_string_table(ElfStringTable* table) {
227  if (m_string_tables == NULL) {
228    m_string_tables = table;
229  } else {
230    table->m_next = m_string_tables;
231    m_string_tables = table;
232  }
233}
234
235ElfStringTable* ElfFile::get_string_table(int index) {
236  ElfStringTable* p = m_string_tables;
237  while (p != NULL) {
238    if (p->index() == index) return p;
239    p = p->m_next;
240  }
241  return NULL;
242}
243
244#ifdef LINUX
245bool ElfFile::specifies_noexecstack(const char* filepath) {
246  // Returns true if the elf file is marked NOT to require an executable stack,
247  // or if the file could not be opened.
248  // Returns false if the elf file requires an executable stack, the stack flag
249  // is not set at all, or if the file can not be read.
250  if (filepath == NULL) return true;
251
252  FILE* file = fopen(filepath, "r");
253  if (file == NULL)  return true;
254
255  // AARCH64 defaults to noexecstack. All others default to execstack.
256#ifdef AARCH64
257  bool result = true;
258#else
259  bool result = false;
260#endif
261
262  // Read file header
263  Elf_Ehdr head;
264  if (fread(&head, sizeof(Elf_Ehdr), 1, file) == 1 &&
265      is_elf_file(head) &&
266      fseek(file, head.e_phoff, SEEK_SET) == 0) {
267
268    // Read program header table
269    Elf_Phdr phdr;
270    for (int index = 0; index < head.e_phnum; index ++) {
271      if (fread((void*)&phdr, sizeof(Elf_Phdr), 1, file) != 1) {
272        result = false;
273        break;
274      }
275      if (phdr.p_type == PT_GNU_STACK) {
276        result = (phdr.p_flags == (PF_R | PF_W));
277        break;
278      }
279    }
280  }
281  fclose(file);
282  return result;
283}
284#endif // LINUX
285
286#endif // !_WINDOWS && !__APPLE__
287