facb87f672
Description: 增加ocr接口的单元测试 Log: no Change-Id: Ie78bb8f8d2def33ce441857daef52bdc4efa5650
281 lines
8.6 KiB
C++
Executable File
281 lines
8.6 KiB
C++
Executable File
#ifndef __ADDR_ANY_H__
|
|
#define __ADDR_ANY_H__
|
|
|
|
|
|
//linux
|
|
#include <regex.h>
|
|
#include <cxxabi.h>
|
|
//c
|
|
#include <cinttypes>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
|
|
//c++
|
|
#include <string>
|
|
#include <map>
|
|
//project
|
|
#include "elfio.hpp"
|
|
|
|
|
|
|
|
class AddrAny
|
|
{
|
|
public:
|
|
AddrAny()
|
|
{
|
|
m_init = get_exe_pathname(m_fullname);
|
|
m_baseaddr = 0;
|
|
}
|
|
AddrAny(std::string libname)
|
|
{
|
|
m_init = get_lib_pathname_and_baseaddr(libname, m_fullname, m_baseaddr);
|
|
}
|
|
|
|
int get_local_func_addr_symtab(std::string func_name_regex_str, std::map<std::string,void*>& result)
|
|
{
|
|
return get_func_addr(SHT_SYMTAB, STB_LOCAL, func_name_regex_str, result);
|
|
}
|
|
int get_global_func_addr_symtab(std::string func_name_regex_str, std::map<std::string,void*>& result)
|
|
{
|
|
return get_func_addr(SHT_SYMTAB, STB_GLOBAL, func_name_regex_str, result);
|
|
}
|
|
int get_weak_func_addr_symtab(std::string func_name_regex_str, std::map<std::string,void*>& result)
|
|
{
|
|
return get_func_addr(SHT_SYMTAB, STB_WEAK, func_name_regex_str, result);
|
|
}
|
|
|
|
int get_global_func_addr_dynsym( std::string func_name_regex_str, std::map<std::string,void*>& result)
|
|
{
|
|
return get_func_addr(SHT_DYNSYM, STB_GLOBAL, func_name_regex_str, result);
|
|
}
|
|
int get_weak_func_addr_dynsym(std::string func_name_regex_str, std::map<std::string,void*>& result)
|
|
{
|
|
return get_func_addr(SHT_DYNSYM, STB_WEAK, func_name_regex_str, result);
|
|
}
|
|
|
|
private:
|
|
bool demangle(std::string& s, std::string& name) {
|
|
int status;
|
|
char* pname = abi::__cxa_demangle(s.c_str(), 0, 0, &status);
|
|
if (status != 0)
|
|
{
|
|
switch(status)
|
|
{
|
|
case -1: name = "memory allocation error"; break;
|
|
case -2: name = "invalid name given"; break;
|
|
case -3: name = "internal error: __cxa_demangle: invalid argument"; break;
|
|
default: name = "unknown error occured"; break;
|
|
}
|
|
return false;
|
|
}
|
|
name = pname;
|
|
free(pname);
|
|
return true;
|
|
}
|
|
bool get_exe_pathname( std::string& name)
|
|
{
|
|
char line[512];
|
|
FILE *fp;
|
|
uintptr_t base_addr;
|
|
char perm[5];
|
|
unsigned long offset;
|
|
int pathname_pos;
|
|
char *pathname;
|
|
size_t pathname_len;
|
|
int match = 0;
|
|
|
|
if(NULL == (fp = fopen("/proc/self/maps", "r")))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
while(fgets(line, sizeof(line), fp))
|
|
{
|
|
if(sscanf(line, "%" PRIxPTR "-%*lx %4s %lx %*x:%*x %*d%n", &base_addr, perm, &offset, &pathname_pos) != 3) continue;
|
|
|
|
if(0 != offset) continue;
|
|
|
|
//get pathname
|
|
while(isspace(line[pathname_pos]) && pathname_pos < (int)(sizeof(line) - 1))
|
|
pathname_pos += 1;
|
|
if(pathname_pos >= (int)(sizeof(line) - 1)) continue;
|
|
pathname = line + pathname_pos;
|
|
pathname_len = strlen(pathname);
|
|
if(0 == pathname_len) continue;
|
|
if(pathname[pathname_len - 1] == '\n')
|
|
{
|
|
pathname[pathname_len - 1] = '\0';
|
|
pathname_len -= 1;
|
|
}
|
|
if(0 == pathname_len) continue;
|
|
if('[' == pathname[0]) continue;
|
|
|
|
name = pathname;
|
|
match = 1;
|
|
break;
|
|
|
|
}
|
|
fclose(fp);
|
|
|
|
if(0 == match)
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
bool get_lib_pathname_and_baseaddr(std::string pathname_regex_str, std::string& name, unsigned long& addr)
|
|
{
|
|
char line[512];
|
|
FILE *fp;
|
|
uintptr_t base_addr;
|
|
char perm[5];
|
|
unsigned long offset;
|
|
int pathname_pos;
|
|
char *pathname;
|
|
size_t pathname_len;
|
|
int match;
|
|
regex_t pathname_regex;
|
|
|
|
regcomp(&pathname_regex, pathname_regex_str.c_str(), 0);
|
|
|
|
if(NULL == (fp = fopen("/proc/self/maps", "r")))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
while(fgets(line, sizeof(line), fp))
|
|
{
|
|
if(sscanf(line, "%" PRIxPTR "-%*lx %4s %lx %*x:%*x %*d%n", &base_addr, perm, &offset, &pathname_pos) != 3) continue;
|
|
|
|
//check permission
|
|
if(perm[0] != 'r') continue;
|
|
if(perm[3] != 'p') continue; //do not touch the shared memory
|
|
|
|
//check offset
|
|
//
|
|
//We are trying to find ELF header in memory.
|
|
//It can only be found at the beginning of a mapped memory regions
|
|
//whose offset is 0.
|
|
if(0 != offset) continue;
|
|
|
|
//get pathname
|
|
while(isspace(line[pathname_pos]) && pathname_pos < (int)(sizeof(line) - 1))
|
|
pathname_pos += 1;
|
|
if(pathname_pos >= (int)(sizeof(line) - 1)) continue;
|
|
pathname = line + pathname_pos;
|
|
pathname_len = strlen(pathname);
|
|
if(0 == pathname_len) continue;
|
|
if(pathname[pathname_len - 1] == '\n')
|
|
{
|
|
pathname[pathname_len - 1] = '\0';
|
|
pathname_len -= 1;
|
|
}
|
|
if(0 == pathname_len) continue;
|
|
if('[' == pathname[0]) continue;
|
|
|
|
//check pathname
|
|
//if we need to hook this elf?
|
|
match = 0;
|
|
if(0 == regexec(&pathname_regex, pathname, 0, NULL, 0))
|
|
{
|
|
match = 1;
|
|
name = pathname;
|
|
addr = (unsigned long)base_addr;
|
|
break;
|
|
}
|
|
if(0 == match) continue;
|
|
|
|
}
|
|
fclose(fp);
|
|
if(0 == match)
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
int get_func_addr(unsigned int ttype, unsigned int stype, std::string& func_name_regex_str, std::map<std::string,void*>& result)
|
|
{
|
|
// Create an elfio reader
|
|
ELFIO::elfio reader;
|
|
int count = 0;
|
|
regex_t pathname_regex;
|
|
|
|
if(!m_init)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
regcomp(&pathname_regex, func_name_regex_str.c_str(), 0);
|
|
// Load ELF data
|
|
if(!reader.load(m_fullname.c_str()))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
ELFIO::Elf_Half sec_num = reader.sections.size();
|
|
for(int i = 0; i < sec_num; ++i)
|
|
{
|
|
ELFIO::section* psec = reader.sections[i];
|
|
// Check section type
|
|
if(psec->get_type() == ttype)
|
|
{
|
|
const ELFIO::symbol_section_accessor symbols( reader, psec );
|
|
for ( unsigned int j = 0; j < symbols.get_symbols_num(); ++j )
|
|
{
|
|
std::string name;
|
|
std::string name_mangle;
|
|
ELFIO::Elf64_Addr value;
|
|
ELFIO::Elf_Xword size;
|
|
unsigned char bind;
|
|
unsigned char type;
|
|
ELFIO::Elf_Half section_index;
|
|
unsigned char other;
|
|
|
|
// Read symbol properties
|
|
symbols.get_symbol( j, name, value, size, bind, type, section_index, other );
|
|
if(type == STT_FUNC && bind == stype)
|
|
{
|
|
bool ret = demangle(name,name_mangle);
|
|
if(ret == true)
|
|
{
|
|
if (0 == regexec(&pathname_regex, name_mangle.c_str(), 0, NULL, 0))
|
|
{
|
|
result.insert ( std::pair<std::string,void *>(name_mangle,(void*)(value + m_baseaddr)));
|
|
count++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (0 == regexec(&pathname_regex, name.c_str(), 0, NULL, 0))
|
|
{
|
|
result.insert ( std::pair<std::string,void *>(name,(void*)(value + m_baseaddr)));
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
private:
|
|
bool m_init;
|
|
std::string m_name;
|
|
std::string m_fullname;
|
|
unsigned long m_baseaddr;
|
|
|
|
};
|
|
#endif
|