debugger(四):源代码
〇、前言
终于来到令人激动的源代码 level 了,这里将会有一些很有意思的算法,来实现源代码级别的调试,这将会非常有趣。
一、使用 libelfin 库
我们不可能直接去读取整个 .debug info 段来进行设置,这是没有必要的,可以使用现成的库。首先初始化 debugger 对象:
class debugger {
public:debugger (std::string prog_name, pid_t pid): m_prog_name{std::move(prog_name)}, m_pid{pid} {auto fd = open(m_prog_name.c_str(), O_RDONLY);m_elf = elf::elf{elf::create_mmap_loader(fd)};m_dwarf = dwarf::dwarf{dwarf::elf::create_loader(m_elf)};}//...private://...dwarf::dwarf m_dwarf;elf::elf m_elf;
};
不必太过关注这里函数的细节,只需要关注它们做了什么。事实上,m_dwarf、m_elf 和 文件名 m_prog_name 关联起来了,然后就交给它们进行处理了。我们还需要知道 load_addr,这非常重要,因为debuf info 只会提供静态的信息,load_addr 取决于运行时,因此得想办法在 /proc 中获取:
void Debugger::initialise_load_address() {if (m_elf.get_hdr().type == elf::et::dyn) {std::ifstream map("/proc/" + std::to_string(m_pid) + "/maps");//Read the first address from the filestd::string addr;std::getline(map, addr, '-');m_load_address = std::stoi(addr, 0, 16);}
}
二、获取信息
通过一个 pc 怎么获取函数名呢?注意这个 pc 是一个 offset addr,传参的时候一定要转换。思路很简单,首先遍历所有的 cu,然后判断 cu 的 low_pc 和 high_pc,如果在这个 cu 符合,那么就通过 cu 拿到 cu.root。cu.root 是一个根 die,通过它可以遍历所有的 die。之后再判断 die的 tag 是不是一个函数,如果是且包含 pc,那么就是我们要找的函数。实现如下:
dwarf::die Debugger::get_function_from_pc(std::intptr_t pc) {for (auto &cu : m_dwarf.compilation_units()) { // 循环遍历所有cuif (die_pc_range(cu.root()).contains(pc)) {for (const auto &die :cu.root()) { if (die.tag ==dwarf::DW_TAG::subprogram) { if (die_pc_range(die).contains(pc)) {return die;}}}}}throw std::out_of_range{"Cannot find function"};
}
接着通过 pc 来获取 line entry:
dwarf::line_table::iterator Debugger::get_line_entry_from_pc(uint64_t pc) {for (auto &cu : m_dwarf.compilation_units()) {if (die_pc_range(cu.root()).contains(pc)) {auto < = cu.get_line_table();auto it = lt.find_address(pc);if (it == lt.end()) {throw std::out_of_range{"Cannot find line entry"};}else {return it;}}}throw std::out_of_range{"Cannot find line entry"};
}
接着我们打印源代码。思路是通过 debug info 中的源代码路径和 line table 来获取,好消息是,我们不必做更多的底层实现:
void Debugger::print_source(const std::string& file_name, unsigned line, unsigned n_lines_context) {std::ifstream file {file_name};auto start_line = line <= n_lines_context ? 1 : line - n_lines_context;auto end_line = line + n_lines_context + (line < n_lines_context ? n_lines_context - line : 0) + 1;char c{};auto current_line = 1u;while (current_line != start_line && file.get(c)) {if (c == '\n') {++current_line;}}std::cout << (current_line==line ? "> " : " ");while (current_line <= end_line && file.get(c)) {std::cout << c;if (c == '\n') {++current_line;std::cout << (current_line==line ? "> " : " ");}}std::cout << std::endl;
}
三、测试
minidbg> break 0x555555555191
Set breakpoint at address 0x555555555191
minidbg> conti
Hit breakpoint at adsress 0x555555555191#include <iostream>int main() {
> std::cerr << "hello,world0.\n";return 0;}
我们确实成功的打印出了源代码。上述基本的信息获取,基本思路就是对 DWARF 的理解,然后利用库函数接口获取我们想要的信息。
相关文章:
debugger(四):源代码
〇、前言 终于来到令人激动的源代码 level 了,这里将会有一些很有意思的算法,来实现源代码级别的调试,这将会非常有趣。 一、使用 libelfin 库 我们不可能直接去读取整个 .debug info 段来进行设置,这是没有必要的,…...
基于运动控制卡的圆柱坐标机械臂设计
1 方案简介 介绍一种基于运动控制卡制作一款scara圆柱坐标的机械臂设计方案,该方案控制器用运动控制卡制作一台三轴机械臂,用于自动抓取和放料操作。 2 组成部分 该机械臂的组成部分有研华运动控制卡,触摸屏,三轴圆柱坐标的平面运…...
MongoDBTemplate-基本文档查询
文章目录 流程概述步骤1:创建一个MongoDB的连接步骤2:创建一个查询对象Query步骤3:设置需要查询的字段步骤4:使用查询对象执行查询操作 流程概述 步骤描述步骤1创建一个MongoDB的连接步骤2创建一个查询对象Query步骤3设置需要查询…...
23种设计模式——创建型模式
设计模式 文章目录 设计模式创建型模式单例模式 [1-小明的购物车](https://kamacoder.com/problempage.php?pid1074)工厂模式 [2-积木工厂](https://kamacoder.com/problempage.php?pid1076)抽象⼯⼚模式 [3-家具工厂](https://kamacoder.com/problempage.php?pid1077)建造者…...
idm究竟有哪些优势
IDM(Internet Download Manager)是一款广受好评的下载管理工具,其主要优势包括: 高速下载:IDM支持最大32线程的下载,可以显著提升下载速度1。文件分类下载:IDM可以根据文件后缀进行分类&#x…...
如何学习Golang语言!
第一部分:Go语言概述 起源与设计哲学:Go语言由Robert Griesemer、Rob Pike和Ken Thompson三位Google工程师设计,旨在解决现代编程中的一些常见问题,如编译速度、运行效率和并发编程。主要特点:Go语言的语法简单、编译…...
Redis系列之淘汰策略介绍
Redis系列之淘汰策略介绍 文章目录 为什么需要Redis淘汰策略?Redis淘汰策略分类Redis数据淘汰流程源码验证淘汰流程Redis中的LRU算法Redis中的LFU算法 为什么需要Redis淘汰策略? 由于Redis内存是有大小的,当内存快满的时候,又没有…...
sql 调优
sql 调优 SQL调优是一个复杂的过程,涉及多个方面,包括查询优化、索引优化、表结构优化等。以下是一些基本的SQL调优策略: 使用索引:确保查询中涉及的列都有适当的索引。 查询优化:避免使用SELECT *,只选取…...
【UML用户指南】-13-对高级结构建模-包
目录 1、名称 2、元素 3、可见性 4、引入与引出 用包把建模元素安排成可作为一个组来处理的较大组块。可以控制这些元素的可见性,使一些元素在包外是可见的,而另一些元素要隐藏在包内。也可以用包表示系统体系结构的不同视图。 狗窝并不复杂&#x…...
前端面试题日常练-day63 【面试题】
题目 希望这些选择题能够帮助您进行前端面试的准备,答案在文末 1. TypeScript中,以下哪个关键字用于声明一个类的构造函数? a) constructor b) init c) create d) initialize 2. 在TypeScript中,以下哪个符号用于声明可选的函…...
GAN的入门理解
这一篇主要是关于生成对抗网络的模型笔记,有一些简单的证明和原理,是根据李宏毅老师的课程整理的,下面有链接。本篇文章主要就是梳理基础的概念和训练过程,如果有什么问题的话也可以指出的。 李宏毅老师的课程链接 1.概述 GAN是…...
43【PS 作图】颜色速途
1 通过PS让画面细节模糊,避免被过多的颜色干扰 2 分析画面的颜色 3 作图 参考网站: 色感不好要怎么提升呢?分享一下我是怎么练习色感的!_哔哩哔哩_bilibili https://www.bilibili.com/video/BV1h1421Z76p/?spm_id_from333.1007.…...
定个小目标之刷LeetCode热题(13)
今天来看看这道题,介绍两种解法 第一种动态规划,代码如下 class Solution {public int maxSubArray(int[] nums) {int pre 0, maxAns nums[0];for (int x : nums) {// 计算当前最大前缀和pre Math.max(pre x, x);// 更新最大前缀和maxAns Math.ma…...
【AI大模型】Prompt Engineering
目录 什么是提示工程(Prompt Engineering) Prompt 调优 Prompt 的典型构成 「定义角色」为什么有效? 防止 Prompt 攻击 攻击方式 1:著名的「奶奶漏洞」 攻击方式 2:Prompt 注入 防范措施 1:Prompt 注…...
centos安装vscode的教程
centos安装vscode的教程 步骤一:打开vscode官网找到历史版本 历史版本链接 步骤二:找到文件下载的位置 在命令行中输入(稍等片刻即可打开): /usr/share/code/bin/code关闭vscode后,可在应用程序----编程…...
面试题------>MySQL!!!
一、连接查询 ①:左连接left join (小表在左,大表在右) ②:右连接right join(小表在右,大表在左) 二、聚合函数 SQL 中提供的聚合函数可以用来统计、求和、求最值等等 COUNT&…...
英伟达:史上最牛一笔天使投资
200万美元的天使投资,让刚成立就面临倒闭风险的英伟达由危转安,并由此缔造了一个2.8万亿美元的市值神话。 这是全球风投史上浓墨重彩的一笔。 前不久,黄仁勋在母校斯坦福大学的演讲中,提到了人生中的第一笔融资——1993年&#x…...
PDF分页处理:技术与实践
引言 在数字化办公和学习中,PDF文件因其便携性和格式稳定性而广受欢迎。然而,处理大型PDF文件时,我们经常需要将其拆分成单独的页面,以便于管理和分享。本文将探讨如何使用Python编程语言和一些流行的库来实现PDF文件的分页处理。…...
数据可视化——pyecharts库绘图
目录 官方文档 使用说明: 点击基本图表 可以点击你想要的图表 安装: 一些例图: 柱状图: 效果: 折线图: 效果: 环形图: 效果: 南丁格尔图(玫瑰图&am…...
Python的return和yield,哪个是你的菜?
目录 1、return基础介绍 📚 1.1 return用途:数据返回 1.2 return执行:函数终止 1.3 return深入:无返回值情况 2、yield核心概念 🍇 2.1 yield与迭代器 2.2 生成器函数构建 2.3 yield的暂停与续行特性 3、retur…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
