能定位修改代码后被影响的二进制文件吗?

happyhuang 2008-05-21 08:39:17
困扰我许久的问题。

背景是需要给一个很大的系统作补丁,最后提供的就是几个需要重新覆盖安装的二进制文件。

比如,string.cpp里面的strcat()函数被修改了,那么所有调用strcat()的库文件、可执行文件都需要提供给客户。
而所有仅仅调用strcpy()函数的那些库文件都不需要提供。

现在的办法是在浩如烟海的代码和Makefile中寻找被影响的文件,但是效率太低而且太容易出错了。

大家有什么好办法吗?
...全文
223 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
fuqd273 2008-05-22
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 happyhuang 的回复:]
我原来也是这么觉得的,后来发现所有动态链接的目标文件都有时间更新,而我们只需要提供其中的动态链接库即可。

比如楼上举的例子:
cc -o test test.c -L/etc/lib/stdlib -lmylab

make会在两种情况下重新编译产生test目标文件。
1、test.c发生了改动
2、libmylab.so发生了改动

第二种情况,如果只…
[/Quote]
建议:
1、整体发布的情况:按照现有流程,但是最好是自动化实现,即、由顶层makefile实现批处理
2、差分发布的情况(也就是你需要的这种情况):在生成mylab的时候,不要在-L/etc/lib/stdlib 处产生最新的libmylab.so/libmylab.lib。这是可以做到的、例如,采用通过环境变量控制流程的条件编译。这样,在编译test.c的时候,就不会因为libmylab.so变化而更新了。

另:从你给出的makefile来看,已经有统一的lib管理路径,只需要略加修正就可以了。
happyhuang 2008-05-22
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 coding_hello 的回复:]
奇怪,MakeFile不就是干这活的吗? 把编译后的时间更新的挑出来不就完了
[/Quote]
我原来也是这么觉得的,后来发现所有动态链接的目标文件都有时间更新,而我们只需要提供其中的动态链接库即可。

比如楼上举的例子:
cc -o test test.c -L/etc/lib/stdlib -lmylab

make会在两种情况下重新编译产生test目标文件。
1、test.c发生了改动
2、libmylab.so发生了改动

第二种情况,如果只是libmylab.so发生了改动,那么需要提供给用户的补丁只需要libmylab.so,而不需要提供test(因为是动态链接,接口不变的话,test不受影响),但是两个目标文件test和libmylab.so的时间都被更新了。

现在最大的问题就是如何通过脚本剔除这些动态链接库。
难道要我们去解析Makefile吗?还是能通过对目标文件执行某些命令就能发现哪些库是动态链接的?
野男孩 2008-05-22
  • 打赏
  • 举报
回复
奇怪,MakeFile不就是干这活的吗? 把编译后的时间更新的挑出来不就完了
boyzhang 2008-05-22
  • 打赏
  • 举报
回复
用特征码试试,和VC的增量编译差不多.

以前自己写的一个嵌入式系统的源代码,发给客户了,

过了很长时间,说要改,源代码不知道放到那里去了,

只是改几个界面的上文字,于是,就用WinHex直接写二进制改的,

建议你也可以把修改过的函数的特征码找出来,自己做个二进制

特征码搜索工具,把调用了该函数的文件都更新一下就行了.
fuqd273 2008-05-21
  • 打赏
  • 举报
回复
如果是静态连接……
抱歉,我没有更好的办法。
全部重新编译系统恐怕是最快的、最便捷的方法了。
fuqd273 2008-05-21
  • 打赏
  • 举报
回复
印象中lyricEdit.lib 里面只是提供了函数名和参数?
真正的函数指针是libstring.so提供的。
换言之,除非修改了函数接口(简单地说,就是连头文件的声明都发生了变化的情况),lib文件不需要替换。
而函数实体发生变化的话,对应的so文件需要全部更新。

否则……封装成动态库还有什么意义么?
fuqd273 2008-05-21
  • 打赏
  • 举报
回复
lyricEdit.lib 需要提供么?
你采取了需要修正lyricEdit.lib 的修改方法?
happyhuang 2008-05-21
  • 打赏
  • 举报
回复
-------------------- 代码

///// string.cpp

string::diskSave()
{
cout<<"Save to disk"<<endl;
}

string::show()
{
cout<<"Show string"<<endl;
}

///// lyricEdit.cpp

lyric::edit()
{
string a;
a.show();
a.edit();
a.diskSave(); /// <------ 调用
}

////// lyricShow.cpp

lyric::show()
{
string a;
a.show();
}

-------------------- Makefile

gcc string.cpp -shared -o libstring.so
gcc lyricEdit.cpp -lstring -o lyricEdit.lib
gcc lyricShow.cpp -lstring -o lyricShow.lib

-------------------- 修改

string::diskSave()
{
/// cout<<"Save to disk"<<endl;
cout<<"function changed!"<<endl;
}

修改之后
1. 需要向用户提供的补丁文件就是libstring.so和lyricEdit.lib
2. lyricShow.lib不需要提供,因为他没有调用diskSave()函数

不知道这样说清楚了吗?

我的问题是
3. 除了通读代码之外,有什么更好的办法能自动找出需要提供的补丁文件吗(lyricEdit.lib)?

以上3点,有哪一点看不明白,请指出,谢谢。

babyvox1999 2008-05-21
  • 打赏
  • 举报
回复
我们很容易知道string::diskSave()修改了之后string.lib需要重新安装。可是要如何去寻找lyricEdit.lib呢?尤其是整个系统有成百上千个lib文件的时候。
========================================================
不明白什么意思
happyhuang 2008-05-21
  • 打赏
  • 举报
回复
举个例子,假设我们的产品是MediaPlayer,其中包含了如下库文件和歌词:

decode.lib 音频解码
lyricShow.lib 显示歌词
lyricEdit.lib 歌词编辑器
help.lib 帮助,出错信息提示
string.lib string::show()
string::diskSave()

调用关系是
lyricShow.lib ----> string::show()
lyricEdit.lib -+--> string::show()
|
+--> string::diskSave()
help.lib ---------> string::show()

现在string.lib里面的string::diskSave()函数发现了bug,并已经改好了。需要提供的补丁安装包将包含两个二进制文件:lyricEdit.lib和string.lib

我们很容易知道string::diskSave()修改了之后string.lib需要重新安装。可是要如何去寻找lyricEdit.lib呢?尤其是整个系统有成百上千个lib文件的时候。

WingForce 2008-05-21
  • 打赏
  • 举报
回复
不是有所谓的动态链接技术么。。。
happyhuang 2008-05-21
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 fuqd273 的回复:]
所以我列举了2种情况啊。

用shell脚本不能把筛选出来1的那部分筛选出来么?
首先找到所有的变更文件,然后去掉不是由于代码变动、而是由于链接库变动而生成的目标文件。不就OK了么?
[/Quote]

挺清楚的,谢谢。接下来的问题恐怕是要怎么把1的情况筛选出来。

我把我工作中碰到的实际情况贴上来吧。

-----------------------------------------------------------
1、我修改了一个协议处理的源文件:

/projects/ESPN/source/Protocol/Msg/v32/protocol.cpp

-----------------------------------------------------------
2、该目录下的Makefile定义了怎样去编译这个源文件:

# 机器类型4254
MSGVAR32GEN_E4254A_OBJECTS = $(MSGVAR32GEN_HPUX32_OBJECTS:$(SDB_PA32HPUX_SF).o=$(SDB_E4254A_SF).o) \
$(addprefix $(MSGVAR32GEN)/$(DERIVEDOBJS)/, \
ProtocolPP_$(SDB_E4254A_SF).o \
Protocol_$(SDB_E4254A_SF).o )

# 机器类型6741
MSGVAR32GEN_J6741A_OBJECTS = $(MSGVAR32GEN_E4254A_OBJECTS:$(SDB_E4254A_SF).o=$(SDB_J6741A_SF).o)

# 机器类型7557
MSGVAR32GEN_E7557A_OBJECTS = $(MSGVAR32GEN_E4254A_OBJECTS:$(SDB_E4254A_SF).o=$(SDB_E7557A_SF).o)

-----------------------------------------------------------
3、要提供的库在这里找到

/projects/ESPN/source/Protocol/IfpcLib/Makefile

# 机器类型6741
SDBPROTOCOL_IFPCLIB_J6741A_OBJECTS = $(SDBPROTOCOL_COM_J6741A_OBJECTS) \
$(BUFFERPLUS_CORE_J6741A_OBJECTS) \
$(BUFFERPLUS_P7_PAP_J6741A_OBJECTS) \
$(PAPINT_COM_J6741A_OBJECTS) \
$(PAPINT_V29_J6741A_OBJECTS) \
$(PAPINT_V30_J6741A_OBJECTS) \
$(PAPINT_V32_J6741A_OBJECTS) \
$(PAPINT_V34_J6741A_OBJECTS) \
$(MSGVAR29_J6741A_OBJECTS) \
$(MSGVAR30_J6741A_OBJECTS) \
$(MSGVAR32GEN_J6741A_OBJECTS) \
$(MSGVAR34_J6741A_OBJECTS)

SDBPROTOCOL_IFPCLIB_J6741A_LIBS = $(SDB_ZLIB_BPP_LIB_DIR)/libz.a

SDBPROTOCOL_IFPCLIB_J6741A_TARGET = $(SDBPROTOCOL_IFPCLIB_E4254A_TARGET:$(SDB_E4254A_SF).sl=$(SDB_J6741A_SF).sl)

$(SDBPROTOCOL_IFPCLIB_J6741A_TARGET) : $(SDBPROTOCOL_IFPCLIB_J6741A_OBJECTS) \
$(SDBPROTOCOL_IFPCLIB_J6741A_LIBS)

-----------------------------------------------------------
我的工作流程:
1、把源文件protocol.cpp改好
2、在当前目录下的Makefile里面找对应的.o文件是怎么编译的,找到宏定义MSGVAR32GEN_E4254A_OBJECTS...
3、grep所有目录下的所有Makefile,找MSGVAR32GEN_E4254A_OBJECTS...
终于找到在/projects/ESPN/source/Protocol/IfpcLib/中,有一个J6741A_TARGET引用了这个object文件,于是这个目标文件需要提供给客户。

如果我每改一个源文件就要这样,效率太低了。

如果用你建议的方法,不知道要怎么把情况1筛选出来呢?
fuqd273 2008-05-21
  • 打赏
  • 举报
回复
或者——
所有的makefile增加switch开关,
在指定情况下,不更新install目录下的so/lib。
fuqd273 2008-05-21
  • 打赏
  • 举报
回复
不明白既然已经离目的地那么近了,还在兜圈子……
fuqd273 2008-05-21
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 happyhuang 的回复:]
如果只是libmylab.so发生了改动,那么需要提供给用户的补丁是libmylab.so,而不需要提供test(因为是动态链接)
但是现在make会重新生成新的test目标文件。

所以,通过脚本判断make生成的目标文件新旧,是不足以区分出需要提供给用户的补丁的。[/Quote]

所以我列举了2种情况啊。

用shell脚本不能把筛选出来1的那部分筛选出来么?
首先找到所有的变更文件,然后去掉不是由于代码变动、而是由于链接库变动而生成的目标文件。不就OK了么?

happyhuang 2008-05-21
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 fuqd273 的回复:]
例如:

cc -o test test.c -L/etc/lib/stdlib -lmylab

make会在两种情况下重新编译产生test目标文件。
1、test.c发生了改动
2、libmylab.so发生了改动

够清楚了么?

[/Quote]

如果只是libmylab.so发生了改动,那么需要提供给用户的补丁是libmylab.so,而不需要提供test(因为是动态链接)
但是现在make会重新生成新的test目标文件。

所以,通过脚本判断make生成的目标文件新旧,是不足以区分出需要提供给用户的补丁的。
fuqd273 2008-05-21
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 happyhuang 的回复:]
比如这种情况:一个头文件里声明了两个类,class a增加了函数;class b没有动,所有include这个头文件的so库都要重新编译。可是实际上应该只是用class a的so库才真正受到了影响。[/Quote]

你确定只有用到class a 的程序才受到影响?
参照了class b的程序不受影响么?
你真的确定?


fuqd273 2008-05-21
  • 打赏
  • 举报
回复
例如:

cc -o test test.c -L/etc/lib/stdlib -lmylab

make会在两种情况下重新编译产生test目标文件。
1、test.c发生了改动
2、libmylab.so发生了改动

够清楚了么?
happyhuang 2008-05-21
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 fuqd273 的回复:]
make本身提供自动查询最新目标文件的功能。
换言之,既然已知是很复杂的大型项目,不理解为什么不采用整体makefile进行统一编译的方式。
采用父makefile调用子makefile的形式更新so库。
[/Quote]
> 1. 关于make的查询最新目标文件
比如这种情况:一个头文件里声明了两个类,class a增加了函数;class b没有动,所有include这个头文件的so库都要重新编译。可是实际上应该只是用class a的so库才真正受到了影响。
> 2. 采用父makefile调用子makefile的形式更新so库
我们的系统是这样设计的。只是不知道面对这些父makefile和子makefile,要怎么去找真正受影响的so库呢?
fuqd273 2008-05-21
  • 打赏
  • 举报
回复
如果说,你的问题是,将混杂在一起的最新版本目标文件与旧版本目标文件区分开。

方法之一:shell编程
楼下继续。
加载更多回复(3)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧