零.C语言入口函数

从第一天学习C语言开始,我们的脑子里就深深烙下这样一个概念:C语言程序总是从main()函数开始执行,main()函数结束,程序也就结束了.在平时的练习中貌似这没有问题,但事实真的是这样吗?测试一下,

点击(此处)折叠或打开

#include

#include

#include

int enter(void)

{

printf("the start function!\n");

return 0;

}

编译:

打印处一页错误,其中有这样一条:

crt1.o:In function `__start':(.text+0x20): undefined reference to `main'

字面翻译就是:在函数_start中,main没有定义. __start函数是什么?main还要定义?crtl.o又是什么?带着疑问,我打开了百度.在其中搜到这样一份伪代码:

section .text:

__start:

:

init stack;

init heap;

open stdin;

open stdout;

open stderr;

:

push argv;

push argc;

call _main; (调用 main)

:

destory heap;

close stdin;

close stdout;

close stderr;

:

call __exit;

终于找到了,原来main就躲在crt1.o中,再看__start函数,"start"?不是开始的意思吗?难道每一个C程序就是从这开始的吗?

原来,对于“crt1.o”这个文件,其中crt是“C runtime library”的缩写,其含义是“C运时库”,C运行时库除了给我们提供必要的库函数调用(如memcpy、printf、malloc等)之外,它提供的另一个最重要的功能是为应用程序 添加启动函数。C运行时库启动函数的主要功能为 进行程序的初始化 ,对全局变量进行赋初值 ,加载用户程序的入口函数 。

soga,那这是不是意味着我们可以修改所要加载的入口函数呢?原来还有这样一条命令:

gcc *.c -e -nostartfiles

其中, *.c 为程序的源文件,-e为修改函数的入口地址,e == entrance ,后面的 就指明要替换的函数,-nostartfiles选项的作用是 通知编译器不自动加入启动函数以及别的库级别的初始化 ,这样就不会调用到crt1.o中的_start函数!测试一下,

点击(此处)折叠或打开

#include

#include

#include

int enter(void)

{

printf("the start function!\n");

return 0;

}

编译通过,运行:

the start function!

段错误 (核心已转储)

成功运行enter函数,但提示了段错误.

原来,在编译的时候加上了-nostartfiles这个选项的同时,使得最后的return语句不能正常执行。解决方案是,把程序最后的return语句改成exit()函数,因为return是将控制权交给调用函数,此时我们已经没有调用__start这个函数了,自然就没有enter的调用函数,然而exit()函数是将控制权交给内核,所以能够成功退出.

运行结果:

the start function!

一.LD_PRELOAD

在将LD_PRELOAD之前,我们先来了解一下两种链接方式

静态链接:由链接器在 链接时 将库的内容加入到可执行程序中.

动态链接:在可执行文件 装载时或运行时(注意与静态链接的区别) ,由操作系统的装载程序加载库.

通俗地讲,一种是无论程序运行与否,都加载库(静态库);另一种是只有执行到那一部分代码时,才加载库(动态库).

在Linux的动态链接库的世界中,LD_PRELOAD就是这样一个环境变量,它可以影响程序的运行时的链接(Runtime linker),它允许你定义 在程序运行前 优先加载的动态链接库 .这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数 .通过这个环境变量,我们可以 在主程序和其动态链接库的中间加载别的动态链接库 ,甚至覆盖正常的函数库.

说了这么多,是不是有点模糊?举个例子,

首先先编写一个“strcmp”函数,就将它命名为passwd.c

点击(此处)折叠或打开

#include

int strcmp(const char *str1,const char *str2)

{

puts(str1);

puts(str2);

return 0;

}

执行下面的语句:

gcc passwd.c -shared -o passwd.so -fPIC

其中,-shared选项的意思是将passwd.c编译链接成为一个动态库.*.so在Linux中为共享库——shared object,用于动态链接,和Windows下的dll差不多.

在shell中执行程序时,shell会提供一组环境变量.其中export的作用就是新增一个环境变量,供后续执行的程序使用.export的效力仅及于该此登陆操作.

对于-fPIC,-f后面跟一些编译选项,PIC是其中一种,表示生成位置无关代码(Position Independent Code),位置无关码就是可以在进程的任意内存位置执行的目标码,动态链接库必须使用.

然后,我们就用passwd.so这个库来进行优先替换:

export LD_PRELOAD=./passwd.so

我们知道,strcmp()的功能是比较两个字符串,但是在这里我们用passwd.so来代替系统的动态库,测试一下,

点击(此处)折叠或打开

#include

#include

#include

int main(int argc, char *argv[])

{

char *str = "abcdef";

char pass[10];

printf("Please input the passwd:\n");

gets(pass);

if( strcmp(pass,str) == 0 )

{

printf("Login succeed!\n");

}

else

{

printf("Passwd incorrect!\n");

exit(0);

}

return 0;

}

运行结果:

Please input the passwd:

123456

123456

abcdef

Login succeed!

就这样,strcmp()成功被我们替换了...

参考博文---------------------http://blog.sina.com.cn/s/blog_76a864e20101ehuz.html

c语言sin函数返回nan,C语言入口函数和LD_PRELOAD环境变量相关推荐

  1. c语言枚举如何当函数返回值,C语言学习五 — 数组与枚举

    数组 C 语言支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合.数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量. 数组的声明并不是声明一个个单独的变量,比如 numbe ...

  2. C语言练习题,三色球抽取,从3个红球,5个白球,6个黑球中任意取出8个作为一组进行输出。在每组中可以没有黑球,但必须要有红球和白球。编程实现以上功能。用函数返回其组合数,在函数中打印每组的组合

    三色球分组 从3个红球,5个白球,6个黑球中任意取出8个作为一组进行输出.在每组中可以没有黑球,但必须要有红球和白球.编程实现以上功能.用函数返回其组合数,在函数中打印每组的组合 函数原型为: int ...

  3. (14年)2.写一个函数int func(int n)其返回值是n的逆序整数,例如n=123函数返回321.n=72839,函数返回93827

    #include <stdio.h> #include <stdlib.h> /*写一个函数int func(int n)其返回值是n的逆序整数 例如n=123.函数返回321 ...

  4. 初解禁:SDK服务端主程序入口函数SDK服务端主程序入口函数

    /******************************************************************** 函 数 名: main 功能描述: SDK服务端主程序入口函 ...

  5. ostream作为函数返回值_GO语言基础函数

    GO语言基础–函数 函数是组织好的.可重复使用的.用于执行指定任务的代码块.本文介绍了Go语言中函数的相关内容. 函数定义 Go语言中定义函数使用func关键字,具体格式如下: func 函数名(参数 ...

  6. C语言 const 修饰函数返回值 - C语言零基础入门教程

    目录 一.const 简介 1.const 修饰变量 2.const 修饰指针 二.const 修饰在函数名前面 三.const 修饰在函数名后面 四.猜你喜欢 零基础 C/C++ 学习路线推荐 : ...

  7. c语言子函数返回值,C语言函数说明与返回值

    在学习C语言函数以前,我们需要了解什么是模块化程序设计方法. 人们在求解一个复杂问题时,通常采用的是逐步分解.分而治之的方法,也就是把一个大问题分解成若干个比较容易求解的小问题,然后分别求解.程序员在 ...

  8. void*作为函数返回类型(C语言)

    返回void*的情况 void*作为函数的返回类型的情况 导入 void*介绍 代码示例 结论 void*作为函数的返回类型的情况 导入  C语言中有一种返回值类型比较特殊,就是void*,void作 ...

  9. c语言中自定义函数返回数组,C语言自定义函数返回数组的方法(图文详解)

    C语言自定义函数返回数组的方法(图文详解) 最近看到一些同学问题,有提到说:如何在一个函数中返回数组呢? 能否直接在自定义 函数中,写成char *类型返回值,直接返回呢?,代码如下: 直接返回str ...

最新文章

  1. python windows错误码
  2. [iOS]提交App报错ERROR ITMS -90207
  3. 重新绑定ItemsSource先设置ItemsSource = null;的原因
  4. 进程创建fork--文件表项继承
  5. C++开发者都应该使用的10个C++11特性
  6. 关联表多数据的批量insert (批量导入,测试19W条数据用时46秒)
  7. 交流电的有效值rms值_【电工基础知识:三、正弦交流电的产生】2正弦交流电的三要素...
  8. Mac vscode 配置latex
  9. MongoDB 宣布已收购数据库托管公司 mLab
  10. Java 基础总结--反射的基本操作
  11. Jsoup爬虫之Java爬虫工具类
  12. Gantt - attachEvent事件监听 - (必须)拥有返回值事件
  13. tf.matmul()和tf.multipy()的区别
  14. NodeJS集成Redis实战
  15. 常见的编程语言的特点与应用领域浅谈
  16. 打印excel html js,前端js打印(导出)excel表格的方法实例
  17. 完美解决Mac无法写入NTFS硬盘——Mounty for NTFS
  18. html5怎么修改图片大小,HTML5 javascript修改canvas的大小
  19. 西南石油大学计科院主页
  20. 冯诺依曼计算机和现代,为什么现代计算机被称为冯·诺依曼结构计算机?

热门文章

  1. git@github.com:Permission denied(publickey).fatal: Could not read form remote repository错误
  2. usb连接不上 艾德克斯电源_艾德克斯HT3150联机和IT6720校准联机记
  3. 腾讯移动分析+html5,FAQ · 腾讯移动分析 文档
  4. 华为新系统鸿蒙能互通吗,「连接」万物的鸿蒙,能拯救华为手机吗?
  5. mysql 主从备份问题_我遇到的mysql主从同步的问题
  6. mysql和jfinal的区别_mysql与JFinal的数据关系-阿里云开发者社区
  7. 分布式和微服务是什么?二者的区别又是什么?
  8. switch语句使用注意事项
  9. php安装mem+cache扩展,安装memcached及php扩展
  10. python 猴子补丁_python面试题精讲——monkey patch(猴子补丁)