添加进程访问函数

This commit is contained in:
gb 2023-02-08 17:03:33 +08:00
parent af5c96ec2e
commit fbca5468f1
3 changed files with 258 additions and 3 deletions

View File

@ -186,13 +186,14 @@ namespace sys_util
}
typedef struct _enum_proc_cb
{
bool process;
bool(*on_found)(uint64_t pid, const char* path_name, void* param);
void* param;
}ENPROCCB, * LPENPROCCB;
static bool found_process(const char* path, bool is_dir, void* param)
{
LPENPROCCB cb = (LPENPROCCB)param;
const char* id = strstr(path + 2, "/");
const char* id = strrchr(path, '/');
uint64_t pid = 0;
std::string path_name("");
@ -212,9 +213,37 @@ namespace sys_util
if (*id)
return true;
path_name = get_module_path(nullptr, pid);
if (cb->process)
{
path_name = get_module_path(nullptr, pid);
id = path_name.c_str();
}
else
{
// get start address of pid to path_name
id = 0;
}
return cb->on_found(pid, path_name.c_str(), cb->param);
return cb->on_found(pid, id, cb->param);
}
static bool on_stack_line_read(char* line, void* param)
{
LPENPROCCB cb = (LPENPROCCB)param;
std::string m(line);
uint64_t off = 0;
size_t pos = m.find("]");
if (pos++ != std::string::npos)
m.erase(0, pos);
trim_left(m);
pos = m.find("+0x");
if (pos != std::string::npos)
{
off = from_hex_str(m.c_str() + pos + 3);
m.erase(pos);
}
return cb->on_found(off, m.c_str(), cb->param);
}
int32_t enum_modules(bool(*on_found)(const char* path_module_name, bool is_dir, void* param),// return false to stop enumeratin
@ -283,9 +312,53 @@ namespace sys_util
cb.on_found = on_found;
cb.param = param;
cb.process = true;
return enum_files("/proc", found_process, &cb, false);
}
uint32_t enum_threads(uint64_t pid, bool(*on_found)(uint64_t tid, void* start_addr, void* param), void* param)
{
ENPROCCB cb;
cb.process = false;
cb.param = param;
*(void**)&cb.on_found = *(void**)&on_found;
return enum_files(("/proc/" + std::to_string(pid) + "/task").c_str(), found_process, &cb, false);
}
uint32_t get_thread_callstack(uint64_t pid, uint64_t tid, bool(*on_found)(uint64_t off, const char* module, void* param), void* param)
{
ENPROCCB cb;
cb.process = false;
cb.param = param;
*(void**)&cb.on_found = *(void**)&on_found;
return read_line(("/proc/" + std::to_string(pid) + "/task/" + std::to_string(tid) + "/stack").c_str(), on_stack_line_read, &cb);
}
uint32_t read_line(const char* file, bool(*on_line)(char* line, void* param), void* param)
{
FILE* src = fopen(file, "rb");
int err = 0;
if (!src)
return errno;
size_t ll = 1024;
char* line = new char[ll];
while (fgets(line, ll - 1, src))
{
if (!on_line(line, param))
break;
memset(line, 0, ll);
}
err = errno;
delete[] line;
fclose(src);
return err;
}
std::string get_module_path(const char* module_name, unsigned pid) // get module full path, nullptr is for main-exe
{
@ -435,5 +508,83 @@ namespace sys_util
return ret;
}
static bool is_char_in(const char* str, char ch)
{
if (ch == 0)
return false;
while (*str)
{
if (*str++ == ch)
return true;
}
return false;
}
bool trim_left(std::string& str, const char* space)
{
int off = 0;
for (; off < str.length(); ++off)
{
if (!is_char_in(space, str[off]))
break;
}
if (off)
str.erase(0, off);
return off > 0;
}
bool trim_right(std::string& str, const char* space)
{
int off = str.length() - 1;
for (; off >= 0; --off)
{
if (!is_char_in(space, str[off]))
break;
}
if (off < str.length() - 1)
{
str.erase(off + 1);
return true;
}
return false;
}
uint64_t from_hex_str(const char* hex, const char** end)
{
uint64_t val = 0;
for (int i = 0; i < 16; ++i)
{
if (*hex >= '0' && *hex <= '9')
{
val <<= 4;
val += *hex - '0';
}
else if (*hex >= 'a' && *hex <= 'f')
{
val <<= 4;
val += *hex - 'a' + 10;
}
else if (*hex >= 'A' && *hex <= 'F')
{
val <<= 4;
val += *hex - 'A' + 10;
}
else
{
break;
}
hex++;
}
if (end)
*end = hex;
return val;
}
}

View File

@ -123,6 +123,9 @@ namespace sys_util
, bool recursive = true // walk recursive
); // return errno
int32_t enum_processes(bool(*on_found)(uint64_t pid, const char* path_name, void* param), void* param);
uint32_t enum_threads(uint64_t pid, bool(*on_found)(uint64_t tid, void* start_addr, void* param), void* param);
uint32_t get_thread_callstack(uint64_t pid, uint64_t tid, bool(*on_found)(uint64_t off, const char* module, void* param), void* param);
uint32_t read_line(const char* file, bool(*on_line)(char* line, void* param), void* param);
std::string get_module_path(const char* module_name = nullptr
, unsigned pid = -1); // get module full path, nullptr is for main-exe
@ -165,4 +168,9 @@ namespace sys_util
int32_t get_memory_info(uint64_t* total, uint64_t* available);
std::string format_readable_bytes(uint64_t bytes); // convert to readable text: 512B, 1.21KB, 1.10MB, 3.45GB, 1,234.56GB ...
std::string get_command_output(const char* cmd, uint16_t max_line_len = 256, bool one_line = true);
// trim string, return whether space trimmed
bool trim_left(std::string& str, const char* space = " \t");
bool trim_right(std::string& str, const char* space = " \t");
uint64_t from_hex_str(const char* hex, const char** end = nullptr); // convert 0x100 to 256. parameter 'end' to receive the stopped position
}

View File

@ -10,8 +10,104 @@
#include "scanner.h"
static bool found_proc(uint64_t pid, const char* path, void* param)
{
uint32_t* cnt = (uint32_t*)param;
printf("%d - %ld: %s\n", ++cnt[0], pid, path);
return true;
}
static bool found_modules(const char* path, bool is_dir, void* param)
{
uint32_t* cnt = (uint32_t*)param;
printf("%d - %s\n", ++cnt[0], path);
return true;
}
static bool found_modules_norepeat(const char* path, bool is_dir, void* param)
{
struct
{
uint32_t cnt;
std::vector<std::string> modules;
}*data = nullptr;
*(void**)&data = param;
if (std::find(data->modules.begin(), data->modules.end(), path) == data->modules.end())
{
printf("%d - %s\n", ++data->cnt, path);
data->modules.push_back(path);
}
return true;
}
static bool on_found_thread(uint64_t tid, void* start_addr, void* param)
{
uint32_t* cnt = (uint32_t*)param;
printf("%d - %p(%u): starting at %p\n", ++cnt[0], tid, tid, start_addr);
return true;
}
static bool on_stack(uint64_t off, const char* module, void* param)
{
uint32_t* cnt = (uint32_t*)param;
printf("%d - %s + %p\n", ++cnt[0], module, off);
return true;
}
int32_t main(int32_t argc, char *argv[])
{
// uint32_t cnt = 0, err = 0;
//
// if(argc >= 2)
// {
// if(strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-?") == 0 || strcmp(argv[1], "-help") == 0)
// {
// printf("usage: proc - no options, to enum all processes\n\
// -?/-h/-help: to show this message\n\
// <pid> [-nrp], to enum process(pid) modules, '-nrp' do not print repeating modules\n\
// <-t pid> [tid], to enum threads or print callstack of given thread\
// ");
// }
// else if(argc >= 3)
// {
// if(strcmp(argv[1], "-t") == 0)
// {
// uint32_t pid = atoi(argv[2]);
// if(argc >= 4)
// err = sys_util::get_thread_callstack(pid, atoi(argv[3]), on_stack, &cnt);
// else
// err = sys_util::enum_threads(pid, on_found_thread, &cnt);
// }
// else if(strcmp(argv[2], "-nrp") == 0)
// {
// struct
// {
// uint32_t cnt = 0;
// std::vector<std::string> modules;
// }data;
// err = sys_util::enum_modules(found_modules_norepeat, &data, atoi(argv[1]));
// }
// }
// else
// err = sys_util::enum_modules(found_modules, &cnt, atoi(argv[1]));
// }
// else
// {
// err = sys_util::enum_processes(found_proc, &cnt);
// }
// if(err)
// printf("error = %d (%s)\n", err, strerror(err));EINVAL;
//
// return 0;
char *oper = argc > 1 ? argv[1] : nullptr;
log_cls::initialize(nullptr);