Open flyer0402 opened 1 year ago
dump内存内容 对应有些内存泄漏问题,可能是一种debug方式 在gdb调试过程中(甚至是在调试coredump时),将程序内存中的内容dump到指定文件中 通过gdb dump出相关内存: dump binary memory memory.bin 0x7f0537f000 0x7f05413000
memory.bin 指定文件。相对路径 通过 hexdump -C memory.bin > 1.txt 命令 ,将内存转成字符串形式,打开文件查询内容
https://yuque.antfin.com/idmdo7/pvtm7i/aic18k?
https://yuque.antfin.com/xsg183219/ggq168/ahe2py
https://blog.csdn.net/diyudong4681/article/details/101201098
cmake 指定c++11 set (CMAKE_CXX_STANDARD 11)
EBPF 比较详细的文档 https://coolshell.cn/articles/22320.html
mlock实现原理 https://www.lmlphp.com/user/92895/article/item/1783132/
https://blog.csdn.net/feelabclihu/article/details/123288206
static void mlockExecutable() { char buf[4096]; char flags[8]; FILE *fp; unsigned long start, end;
fp = fopen("/proc/self/maps", "r");
if (fp) {
while (fgets(buf, sizeof(buf), fp)) {
start = 0;
end = 0;
flags[2] = '\0';
flags[4] = '\0';
sscanf(buf, "%lx-%lx %4c ", &start, &end, flags);
if (start > 0 && end > start && flags[2] == 'x') {
mlock2((void *)start, end - start, MLOCK_ONFAULT);
}
}
fclose(fp);
}
} weston.service LimitMEMLOCK=infinity CapabilityBoundingSet=CAP_SYS_NICE CAP_SYS_RESOURCE CAP_SYS_ADMIN CAP_SYSLOG CAP_DAC_OVERRIDE CAP_NET_ADMIN CAP_NET_RAW CAP_IPC_LOCK
Android关于socket和binder使用场景的选择问题 https://blog.csdn.net/rzleilei/article/details/125770598
内核锁、抢占、中断场景 https://blog.csdn.net/u012294613/article/details/123365262 https://blog.csdn.net/feelabclihu/article/details/129631033?spm=1001.2014.3001.5502 https://blog.csdn.net/chbgoon/article/details/123495480 https://blog.csdn.net/u012294613/article/details/123878531?ops_request_misc=&request_id=093ec2f0ec404ba883be6f38d94381b0&biz_id=&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~koosearch~default-5-123878531-null-null.268^v1^control&utm_term=%E8%87%AA%E6%97%8B%E9%94%81&spm=1018.2226.3001.4450
Linux 环境变量之 LD_PRELOAD & LD_LIBRARY_PATH & LD_DEBUG https://blog.csdn.net/llm_hao/article/details/115493516
g++ attr_test.cpp attr_constructor_test.cpp -fPIC -shared -o libattrtest.so g++ debuggerd_test.cpp -fPIC -shared -o libdebuggerd.so
cp libdebuggerd.so /usr/lib/ cp libdebuggerd.so /usr/lib/ g++ main.cpp -o main -lattrtest -ldl
export LD_LIBRARY_PATH=/workspace/my_debug/attr_constructor/ g++ main.cpp -o main -L. -lattrtest -ldl
// attr_test.cpp
void dosometest() { printf("xxxxxxxxxxxxxxxxxxxxxxx\n"); }
//attr_test.h
void dosometest();
attr_constructor_test.cpp
static void __init_debugger(void) attribute ((constructor));
static void __init_debugger(void) { printf("dhm __init_debugger \n"); void* handle = dlopen("libdebuggerd.so", RTLD_LAZY); if (handle == NULL) { //LOG_E("Fail to load debugger: %s", dlerror()); printf("dhm just test \n"); } }
debuggerd_test.cpp
//#include <sys/stat.h> //#include <sys/ptrace.h> //#include <sys/types.h> //#include <asm/unistd.h>
//#include <sys/syscall.h>
//#include <sys/ptrace.h>
//#include
static void init_debugger_sighandler(void) attribute__ ((constructor));
static void __init_debugger_sighandler(void) { // struct sigaction action; // memset(&action, 0, sizeof(action)); // sigemptyset(&action.sa_mask); // action.sa_sigaction = debuggerd_signal_handler; // action.sa_flags = SA_RESTART | SA_SIGINFO;
printf("dhm __init_debugger_sighandler begin\n");
// sigaction(SIGABRT, &action, NULL); // sigaction(SIGBUS, &action, NULL); // sigaction(SIGFPE, &action, NULL); // sigaction(SIGILL, &action, NULL); // sigaction(SIGSEGV, &action, NULL); // sigaction(SIGTRAP, &action, NULL); } main.cpp
int main() { printf("-----------test main -----------------\n"); dosometest(); return 0; }
dhm __init_debugger dhm __init_debugger_sighandler begin -----------test main ----------------- xxxxxxxxxxxxxxxxxxxxxxx
非法指令(Illegal Instruction)问题定位,比较实用 https://www.cnblogs.com/arnoldlu/p/10815908.html
首先使用simg2img将其解压为raw image, 然后用mount 挂载。
如
out/host/linux-x86/bin/simg2img out/target/product/
Linux RT 进程引发内核频繁卡死的优化方案,RT_RUNTIME_SHARE 解决长期占用问题 https://zhuanlan.zhihu.com/p/592166773 https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-5.4.y&id=423f2695007ddb379b86fceb6c10a42e84794158
PTHREAD_MUTEX_NORMAL
这种类型的互斥锁不会自动检测死锁。如果一个线程试图对一个互斥锁重复锁定,将会引起这个线程的死锁。如果试图解锁一个由别的线程锁定的互斥锁会引发不可预料的结果。如果一个线程试图解锁已经被解锁的互斥锁也会引发不可预料的结果。
PTHREAD_MUTEX_ERRORCHECK
这种类型的互斥锁会自动检测死锁。如果一个线程试图对一个互斥锁重复锁定,将会返回一个错误代码。如果试图解锁一个由别的线程锁定的互斥锁将会返回一个错误代码。如果一个线程试图解锁已经被解锁的互斥锁也将会返回一个错误代码。
PTHREAD_MUTEX_RECURSIVE
如 果一个线程对这种类型的互斥锁重复上锁,不会引起死锁,一个线程对这类互斥锁的多次重复上锁必须由这个线程来重复相同数量的解锁,这样才能解开这个互斥 锁,别的线程才能得到这个互斥锁。如果试图解锁一个由别的线程锁定的互斥锁将会返回一个错误代码。如果一个线程试图解锁已经被解锁的互斥锁也将会返回一个 错误代码。这种类型的互斥锁只能是进程私有的(作用域属性为PTHREAD_PROCESS_PRIVATE)。
PTHREAD_MUTEX_DEFAULT
这种类型的互斥锁不会自动检测死锁。如果一个线程试图对一个互斥锁重复锁定,将会引起不可预料的结果。如果试图解锁一个由别的线程锁定的互斥锁会引发不可预料的结果。如果一个线程试图解锁已经被解锁的互斥锁也会引发不可预料的结果。POSIX标准规定,对于某一具体的实现,可以把这种类型的互斥锁定义为其他类型的互斥锁。 https://www.cnblogs.com/jingzhishen/p/3461727.html
内核工匠-Linux内核性能剖析的方法学和主要工具 https://blog.csdn.net/feelabclihu/article/details/125568230?spm=1001.2014.3001.5502
QNX startup程序分析 https://www.jianshu.com/p/7f4e5bc420fa
linux 浅析安全启动(Secure Boot) https://zhuanlan.zhihu.com/p/540171344
https://www.cnblogs.com/wangbin/p/8862698.html [epoll_wait 时 POLLERR 与 POLLIN 同时返回的现象解析]
codelinaro https://www.codelinaro.org/
codesourcery 和Linaro简介,ARM Toolchain
https://blog.csdn.net/timeless_2014/article/details/82346433
android镜像文件dump出来 cd /dev/block/by-name/ ls -la | grep ivi_app_a lrwxrwxrwx 1 root root 10 Sep 20 15:17 ivi_app_a -> /dev/vda16 dd if=/dev/vda16 of=/sdcard/boot_b.img hexdump /sdcard/boot_b.img https://blog.csdn.net/weixin_43890033/article/details/114966941
namespace { struct Frame { Frame(intptrt **fp) : fp(fp) { callerfp = fp[0]; callerpc = fp[1];
caller_caller_fp_ = reinterpret_cast<intptr_t**>(caller_fp_)[0];
caller_caller_pc_ = reinterpret_cast<intptr_t**>(caller_fp_)[1];
}
~Frame() { intptr_t maybe_callerfp = fp[0]; intptr_t maybe_callerpc = fp[1];
intptr_t *maybe_caller_caller_fp = reinterpret_cast<intptr_t**>(maybe_caller_fp)[0];
intptr_t *maybe_caller_caller_pc = reinterpret_cast<intptr_t**>(maybe_caller_fp)[1];
if ((maybe_caller_fp != caller_fp_) ||
(maybe_caller_pc != caller_pc_) ||
(maybe_caller_caller_fp != caller_caller_fp_) ||
(maybe_caller_caller_pc != caller_caller_pc_)) {
LOG_E("getActiveNetworkStatus stack frame corrupted, abort");
abort();
} else {
LOG_I("caller's frame info, fp: 0x%lx pc: 0x%lx", caller_fp_, caller_pc_);
LOG_I("caller's caller's frame info, fp: 0x%lx pc: 0x%lx", caller_caller_fp_, caller_caller_pc_);
}
}
intptrt **fp;
// v8::internal::FunctionCallbackArguments::Call intptr_t callerfp; intptr_t callerpc;
// v8::internal::HandleApiCallHelper intptr_t caller_callerfp; intptr_t caller_callerpc; }; }
// 函数内使用
void getActiveNetworkStatus(const FunctionCallbackInfo
frame info:
entering getActiveNetworkStatus exiting getActiveNetworkStatus caller's fp 0x7fe5facff0 (x21) 0x7fe5facff0 (x29[0]) caller's pc 0x7fb433ca58 (x25) 0x7fb433ca58 (x29[1]) caller's caler's fp 0x7fe5fad0f0 (x23) 0x7fe5fad0f0 caller's caller's pc 0x7fb433d890 (x24) 0x7f3d5159e8
// 使用mprotect跟踪栈地址,有修改则coredump
void getActiveNetworkStatus(const FunctionCallbackInfo
if (mprotect(aligned_start, aligned_end - aligned_start, PROT_READ) != 0) {
LOG_D("%s error", __func__);
}
LOG_D("%s", __func__);
if (!linkclientReady) {
LOG_E("%s: linkClient is destroyed %p", __func__,&p);
return;
}
auto netStatus = linkClient->getActiveNetworkStatus();
Isolate *isolate = Isolate::GetCurrent();
if (netStatus == NULL) {
LOG_I("getActiveNetworkStatus Null %p %p %p %p %p",fp,&p,&p[1023],aligned_start,aligned_end);
if (mprotect(aligned_start, aligned_end - aligned_start, PROT_READ|PROT_WRITE) != 0) {
LOG_D("%s error", __func__);
}
returnValue(args, Null(isolate));
return;
}
Local<Object> result = Object::New(isolate);
fillNetworkStatus(isolate, *netStatus, result);
LOG_I("getActiveNetworkStatus: %s", netStatus->toString().c_str());
args.GetReturnValue().Set(result);
if (mprotect(aligned_start, aligned_end - aligned_start, PROT_READ|PROT_WRITE) != 0) {
LOG_D("%s error", __func__);
}
通过分析, 栈被踩坏, 踩坏的位置固定 ,尝试对栈添加保护 patch 如下, 栈扩容后,确保子函数栈内地址,在保护地址范围之外 http://gerrit3.alibaba-inc.com/c/git/yunos/tianmu/framework/npm/net_monitor/+/1214777
上述,在栈被踩坏时,触发sig11 ,si_code 2 ,保留了现场 通过coredump 分析, 火山的 _ZN15CompileListener17onCompileProgressEf 向x0写入了一个值,x0 地址是主线程中栈地址 +96 是 调用 onCompileProgress 函数, 通过汇编分析 与调用方代码分析 这个函数地址保存_InleApp中, x0与函数相同方式取出, x0 也是 _InleApp 变量 但没有_InleApp 的数据结构
猜测 compile 函数传的 progress被保存在 InleApp 中, 这个是栈上地址, 只能当前栈内使用 296 float progress = 0; 297 _InleApp->compile(outputFile, "", 1280, 720, 0, 0, -1, 30, 21, &progress/, 4096 2 1024/);
udev基本用法及原理 新的方法是采用NETLINK实现的,这是一种特殊类型的socket,专门用于内核空间与用户空间的异步通信。下面的这个简单的例子,可以监听来自内核hotplug的事件。
include
include
include
include
include <sys/un.h>
include <sys/ioctl.h>
include <sys/socket.h>
include <linux/types.h>
include <linux/netlink.h>
include
include
include <arpa/inet.h>
include <netinet/in.h>
define UEVENT_BUFFER_SIZE 2048
static int init_hotplug_sock()
{
const int buffersize = 1024;
int ret;
struct sockaddr_nl snl;
bzero(&snl, sizeof(struct sockaddr_nl));
snl.nl_family = AF_NETLINK;
snl.nl_pid = getpid();
snl.nl_groups = 1;
int s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
if (s == -1)
{
perror("socket");
return -1;
}
setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize));
ret = bind(s, (struct sockaddr *)&snl, sizeof(struct sockaddr_nl));
if (ret < 0)
{
perror("bind");
close(s);
return -1;
}
return s;
}
int main(int argc, char* argv[])
{
int hotplug_sock = init_hotplug_sock();
while(1)
{
/ Netlink message buffer /
char buf[UEVENT_BUFFER_SIZE * 2] = {0};
recv(hotplug_sock, &buf, sizeof(buf), 0);
printf("%s\n", buf);
} return 0;
}
https://blog.csdn.net/zhaominyong/article/details/127685490