312908509d
Turns out that there's at least two implementations of libelf, one at http://www.mr511.de/software/english.html, and the other at https://fedorahosted.org/elfutils/. One of them has elf_getshstrndx return 0 on success, and the other returns 1. Reviewed By: @scannell Differential Revision: D1095441
98 linhas
2.8 KiB
C++
98 linhas
2.8 KiB
C++
/*
|
|
+----------------------------------------------------------------------+
|
|
| HipHop for PHP |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
|
+----------------------------------------------------------------------+
|
|
| This source file is subject to version 3.01 of the PHP license, |
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
| available through the world-wide-web at the following url: |
|
|
| http://www.php.net/license/3_01.txt |
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
|
|
#include "hphp/util/embedded-data.h"
|
|
#include "hphp/util/current-executable.h"
|
|
|
|
#include "folly/ScopeGuard.h"
|
|
|
|
#include <libelf.h>
|
|
#include <gelf.h>
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#ifdef __APPLE__
|
|
#include <mach-o/getsect.h>
|
|
#endif
|
|
|
|
namespace HPHP { namespace Util {
|
|
|
|
bool get_embedded_data(const char *section, embedded_data* desc,
|
|
const std::string &filename /*= "" */) {
|
|
std::string fname(filename.empty() ? current_executable_path() : filename);
|
|
|
|
#ifndef __APPLE__
|
|
GElf_Shdr shdr;
|
|
size_t shstrndx = -1;
|
|
char *name;
|
|
Elf_Scn *scn;
|
|
|
|
if (elf_version(EV_CURRENT) == EV_NONE) return false;
|
|
|
|
int fd = open(fname.c_str(), O_RDONLY, 0);
|
|
if (fd < 0) return false;
|
|
SCOPE_EXIT { close(fd); };
|
|
|
|
Elf* e = elf_begin(fd, ELF_C_READ, nullptr);
|
|
if (e == nullptr || elf_kind(e) != ELF_K_ELF) {
|
|
return false;
|
|
}
|
|
|
|
auto get_shstrndx =
|
|
#ifdef HAVE_ELF_GETSHDRSTRNDX
|
|
elf_getshdrstrndx;
|
|
#else
|
|
elf_getshstrndx;
|
|
#endif
|
|
|
|
int stat = get_shstrndx(e, &shstrndx);
|
|
if (stat < 0 || shstrndx == size_t(-1)) {
|
|
return false;
|
|
}
|
|
|
|
scn = nullptr;
|
|
while ((scn = elf_nextscn(e, scn)) != nullptr) {
|
|
if (gelf_getshdr(scn, &shdr) != &shdr ||
|
|
!(name = elf_strptr(e, shstrndx , shdr.sh_name))) {
|
|
return false;
|
|
}
|
|
if (!strcmp(section, name)) {
|
|
GElf_Shdr ghdr;
|
|
if (gelf_getshdr(scn, &ghdr) != &ghdr) return false;
|
|
desc->m_filename = fname;
|
|
desc->m_start = ghdr.sh_offset;
|
|
desc->m_len = ghdr.sh_size;
|
|
return true;
|
|
}
|
|
}
|
|
#else // __APPLE__
|
|
const struct section_64 *sect = getsectbyname("__text", section);
|
|
if (sect) {
|
|
desc->m_filename = fname;
|
|
desc->m_start = sect->offset;
|
|
desc->m_len = sect->size;
|
|
return !desc->m_filename.empty();
|
|
}
|
|
#endif // __APPLE__
|
|
return false;
|
|
}
|
|
|
|
} }
|