2312llvm,读写位码

2023-12-16 18:36
文章标签 读写 位码 2312llvm

本文主要是介绍2312llvm,读写位码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

如何读写LLVM位码

首先,看看一些高级LLVM术语:
1,LLVM对用户代码的主要抽象模块.它是一个包含用户编写所有函数,全局变量和指令的类.
2,Bitcode文件是LLVM模块的序化,以便以后可在不同程序中重建它.
3,LLVM使用MemoryBuffer对象来处理文件,stdin数组等数据.

示例中,使用LLVMCAPI.这是LLVM核心C++头文件之上的更稳定的抽象.如果有想同多个版本的LLVM工作的代码,CAPI非常有用,它比LLVMC++头文件稳定得多.
顺便,我在工作中广泛使用LLVM,几乎每周都会有一些LLVMC++头文件更改会破坏代码.而CAPI没有破坏代码.
首先,假设你已拉取了LLVM,构建并安装了它.一些简单的步骤可完成:

git clone https://git.llvm.org/git/llvm.git <llvm dir>
cd <llvm dir>
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=install ..
cmake --build . --target install

完成上述操作后,你就在<llvmdir>/build/install中安装了一个LLVM!
因此,对小可执行文件,使用了CMake.CMake迄今为止是与LLVM整合的最简单方法,因为它也是LLVM使用的构建系统.

project(llvm_bc_parsing_example)
cmake_minimum_required(VERSION 3.4.3)
//允许用户指定`LLVM`在系统上安装位置的选项
set(LLVM_INSTALL_DIR "" CACHE STRING "An LLVM install directory.")
if("${LLVM_INSTALL_DIR}" STREQUAL "")
message(FATAL_ERROR "LLVM_INSTALL_DIR not set! Set it to the location of an LLVM install.")
endif()
//修复路径以仅使用`Linux`约定
string(REPLACE "\\" "/" LLVM_INSTALL_DIR ${LLVM_INSTALL_DIR})
//告诉`CMake`,`LLVM`的模块在哪
list(APPEND CMAKE_MODULE_PATH ${LLVM_INSTALL_DIR}/lib/cmake/llvm)
//包括`LLVM`
include(LLVMConfig)
add_executable(llvm_bc_parsing_example main.c)
target_include_directories(llvm_bc_parsing_example PUBLIC ${LLVM_INCLUDE_DIRS})
target_link_libraries(llvm_bc_parsing_example PUBLIC LLVMBitReader LLVMBitWriter)

现在已安装好CMake,可用现有的LLVM安装目录,现在可处理实际C代码了!
因此,要使用LLVMCAPI,基本上总是需要个头文件:

#include <llvm-c/Core.h>

可执行文件需要两个额外头文件,即位码读取器和写入器:

#include <llvm-c/BitReader.h>
#include <llvm-c/BitWriter.h>

现在创建main函数.在此假设总是正好接受2个命令行参数,第一个是输入文件,第二个是输出文件.LLVM有一个系统,如果提供了叫"-"的文件,即从stdin读写stdout,所以我决定也支持它:

if (3 != argc) {fprintf(stderr, "Invalid command line!\n");return 1;
}
const char *const inputFilename = argv[1];
const char *const outputFilename = argv[2];

因此,首先解析输入文件.从stdin或文件名创建一个LLVM内存缓冲对象:

LLVMMemoryBufferRef memoryBuffer;
//检查是否要从`stdin`读取输入文件
if (('-' == inputFilename[0]) && ('\0' == inputFilename[1])) {char *message;if (0 != LLVMCreateMemoryBufferWithSTDIN(&memoryBuffer, &message)) {fprintf(stderr, "%s\n", message);free(message);return 1;}
} else {char *message;if (0 != LLVMCreateMemoryBufferWithContentsOfFile( inputFilename, &memoryBuffer, &message)) {fprintf(stderr, "%s\n", message);free(message);return 1;}
}

因此,此代码后,可用memoryBuffer读取位码文件LLVM模块中.因此,创建模块!

//现在使用内存缓冲创建的模块
LLVMModuleRef module;
if (0 != LLVMParseBitcode2(memoryBuffer, &module)) {fprintf(stderr, "Invalid bitcode detected!\n");LLVMDisposeMemoryBuffer(memoryBuffer);return 1;
}
//现在使用内存缓冲完成,因此释放掉它
LLVMDisposeMemoryBuffer(memoryBuffer);

一旦有了模块,就不需要内存缓冲,因此可立即释放内存.就这样!取LLVM位码文件,并反序化为LLVM模块.
因此,假设已完成了LLVM模块的所有操作,并想再次写回位码文件.
读取方法一样,查找特殊文件名"-"并相应处理:

//检查是否要把输出文件写入`stdout`
if (('-' == outputFilename[0]) && ('\0' == outputFilename[1])) {if (0 != LLVMWriteBitcodeToFD(module, STDOUT_FILENO, 0, 0)) {fprintf(stderr, "Failed to write bitcode to stdout!\n");LLVMDisposeModule(module);return 1;}
} else {if (0 != LLVMWriteBitcodeToFile(module, outputFilename)) {fprintf(stderr, "Failed to write bitcode to file!\n");LLVMDisposeModule(module);return 1;}
}

最后,清理垃圾,所以删除模块:

LLVMDisposeModule(module);

就这样!现在,可解析并写LLVM位码文件.完整的示例在此

这篇关于2312llvm,读写位码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/501482

相关文章

10. 文件的读写

10.1 文本文件 操作文件三大类: ofstream:写操作ifstream:读操作fstream:读写操作 打开方式解释ios::in为了读文件而打开文件ios::out为了写文件而打开文件,如果当前文件存在则清空当前文件在写入ios::app追加方式写文件ios::trunc如果文件存在先删除,在创建ios::ate打开文件之后令读写位置移至文件尾端ios::binary二进制方式

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

关于使用cspreadsheet读写EXCEL表格数据的问题

前几天项目有读写EXCEL表格的需求,我就找了大概有几种,大致分为:COM方法、ODBC方法、OLE方法、纯底层格式分析方法。由于COM方法要求必须安装有OFFICE的EXCEL组件,纯底层格式分析方法又很多功能需要自行去完善,所有最终选择了数据库的方法,用数据库的方法去存取xls格式的数据。网上有一个高手写的CSpreedSheet,看了一下提供的接口,感觉挺好用的。在使用的过程中发现几个

linux 内核提权总结(demo+exp分析) -- 任意读写(四)

hijack_modprobe_path篇 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm     原理同hijack_prctl, 当用户执行错误格式的elf文件时内核调用call_usermod

linux 内核提权总结(demo+exp分析) -- 任意读写(三)

hijack_prctl篇 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm   prctl函数: 用户态函数,可用于定制进程参数,非常适合和内核进行交互 用户态执行prctl函数后触发prctl系统

linux 内核提权总结(demo+exp分析) -- 任意读写(二)

hijack_vdso篇 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm     vdso: 内核实现的一个动态库,存在于内核,然后映射到用户态空间,可由用户态直接调用 内核中的vdso如果被修改

linux 内核提权总结(demo+exp分析) -- 任意读写(一)

cred篇 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm   每个线程在内核中都对应一个线程结构块thread_infothread_info中存在task_struct类型结构体 struct t

Java 文件读写最好是用buffer对于大文件可以加快速度

参考例子: FileReader fileReader = new FileReader(filename);BufferedReader bufferedReader = new BufferedReader(fileReader);List<String> lines = new ArrayList<String>();String line = null;while ((line =

Java并发:互斥锁,读写锁,Condition,StampedLock

3,Lock与Condition 3.1,互斥锁 3.1.1,可重入锁 锁的可重入性(Reentrant Locking)是指在同一个线程中,已经获取锁的线程可以再次获取该锁而不会导致死锁。这种特性允许线程在持有锁的情况下,可以递归地调用自身的同步方法或代码块,而不会因为再次尝试获取相同的锁而被阻塞。显然,通常的锁都要设计成可重入的。否则就会发生死锁。 synchronized关键字,就是

Windows环境下SD卡多分区 隐藏分区 解决python裸读写扇区失败

SD卡分区 右键“我的电脑”->“管理”->“磁盘管理”; 如果SD卡有文件系统,点击"删除卷",重新做卡; 删除文件系统后如下图,点击“新建简单卷”; 在导航页“指定卷大小”,设置分区的大小,留出剩余的空间; python读写SD卡 这里需要注意的是,写SD卡需要加锁,否则写不成功 #带文件系统,需要锁定卷,否则无法写扇区@contextlib.contextmanagerd