静态替换
针对未被加载的SO,利用复制命令(cp new.so old.so)即可直接完成静态替换,新SO在下次加载时生效。对于已经加载的原SO,直接用新SO复制替换将会导致相应程序崩溃,此种情况可以使用删除原SO(rm -f old.so)或修改原SO名称(mv old.so oldx.so)后,再复制新SO的方法代替,新SO同样在下次加载时生效。
程序崩溃的原因是复制替换 *** 作会破坏系统访问原SO的索引节点inode,导致系统找不到原SO。系统为每个加载到内存中的文件创建对应的inode,用来管理该文件,inode包含了文件的元信息,如文件字节数、拥有者ID、读写执行权限等。系统以inode标识程 序加载的SO,不再关心文件名,修改SO名称并未改变对应inode,因此程序可以继续正常运行;删除SO只是无法查看,系统直到程序释放SO后才真正删除SO和inode,因此程序也可以继续正常运行;但是在直接复制替换时,新SO将会继承原SO的inode,程序无法继续访问原SO,从而导致程序崩溃。
动态替换
针对已经被程序加载的SO,为了实现不停止程序,替换后的SO立即生效的目的,可以采用动态替换。
动态替换的对象既可以是SO整体,也可以是SO中的特定函数。两者的区别主要是整体替换需要在特定函数替换的基础上再增加SO加载及输出函数重定位等过程。由于时间有限, 本文仅介绍特定函数动态替换的基本原理和初步实现,SO整体替换感兴趣的 读者可以自行尝试。
SO特定函数动态替换主要包括三个关键过程:控制目标进程,构造替换内容和确定替换地址,实际上依次解决的就是利用什么替换、替换什么内容和替换到哪里的问题。
#include <stdio.h>#include <string.h>
#include <malloc.h>
// 将strRes中的t替换为s,替换成功返回1,否则返回0。
int StrReplace(char strRes[],char from[], char to[]) {
int i,flag = 0
char *p,*q,*ts
for(i = 0strRes[i]++i) {
if(strRes[i] == from[0]) {
p = strRes + i
q = from
while(*q &&(*p++ == *q++))
if(*q == '\0') {
ts = (char *)malloc(strlen(strRes) + 1)
strcpy(ts,p)
strRes[i] = '\0'
strcat(strRes,to)
strcat(strRes,ts)
free(ts)
flag = 1
}
}
}
return flag
}
int main() {
char str[80] = "098123asd098opu"
printf("替换前:%s\n",str)
if(StrReplace(str,"098","33210")) printf("替换后:%s\n",str)
else printf("没有任何替换。\n")
return 0
}
1、直接用mv移动命令mv a**.cpp b**.c
#移动以a开头.cpp文件并重命名成以b开头.c文件2、用文本处理工具awk *** 作
ls a*.cpp | awk '{n=$0sub(/^a/,"b")sub(/\.cpp$/,".c")system("mv "n" "$0)}'
#ls命令查看所有a开头的.cpp文件,然后|(管道符)传递到awk命令处理,用sub实现第一个位置的替换^a以a开头的替换成b开头。3、用for循环字符串截取方法
for filename in a*.cpp
do
len=${#filename}
newName="b"${filename:1:len-3}
mv $filename $newName
done4、用sed的正则表达式替换
for filename in a*.cpp
do
newName=`echo $filename|sed -r 's/^a(.*\.c)pp$/b\1/'`
#匹配以a开头以.c结尾的文件,然后替换成b
mv $filename $newName
done
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)