Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,9 @@ obj-x86_64-linux-gnu/
.codegraph/
.trellis/
AGENTS.md

# Qt Autotest Generator artifacts
build-autotests/
autotests/.results/
autotests/.reports/
autotests/.ut-session.json
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,11 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
add_subdirectory(tests)
endif()

# Auto-generated unit tests (qt-autotest-generator skill).
# Append-only: only adds a new Debug-gated subdirectory, never touches the
# existing tests/ block above.
enable_testing()
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
add_subdirectory(autotests)
endif()

280 changes: 280 additions & 0 deletions autotests/3rdparty/stub/addr_any.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
#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
Loading
Loading