一代人终将老去,总有人正年轻。


  • 首页

  • 归档

docker-基本概念

发表于 2019-09-06

docker是一个让开发者或管理员通过容器来开发,部署,运行应用的平台。使用容器来部署应用被称为容器化。

容器化变得越来越流行是因为容器有以下特性:

  • 灵活:即使很复杂的应用也可以被容器化
  • 轻量:与宿主机共享内核
  • 热更新:应用运行时部署更新和升级
  • 可移植:可以在本地构建,部署到任何地方
  • 可扩展:可以增加并且自动发布容器副本
  • 可堆叠:可以堆叠服务

Images和Containers

容器通过运行镜像启动。镜像是包含应用运行所需代码,运行时,库,环境变量和配置文件的可执行包。
容器是镜像的运行时实例——当执行的时候镜像加载到内存(也就是有状态的镜像或者用户进程)。可以通过docker ps查看正在运行的容器列表,就像在linux中一样。

Containers和Virtual machines

容器原生的运行在Linux上,并且和其他容器共享宿主及其的内核。它作为一个独立的运行的进程,不占用其他进程的内存,因此很轻量级。

相反,虚拟机运行一个完整的操作系统通过hypervisor虚拟访问主机资源。一般来说,虚拟机提供了多于大部分应用所需的资源环境。

新的开发环境

过去,如果你写一个新的Python应用,第一步是在你的机器上安装Python运行时。并且,创建的环境是应用运行是所期望的,同时也尽可能于正式环境一致。

使用Docker,只需要拿一个可移植的Python运行时作为镜像,不需要安装。然后,构建一个包含基础Python镜像和应用的代码,确保应用的依赖,运行时都在一起。

这些可移植的镜像被DockerFile定义。

使用Dockerfile定义一个容器

Dockerfile定义了你容器中的环境是怎么样的。访问类似网络接口和硬盘驱动被虚拟化进这个环境,这个环境独立于系统的其他部分,所以需要映射端口到外面的世界,并且特别注意你想写进这个环境中的文件。做了这些之后,从Makefile文件中构建的应用无论在什么地方执行都表现出一样的行为。

Dockfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Use an official Python runtime as a parent image
FROM python:2.7-slim

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
COPY . /app

# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

app.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from flask import Flask
from redis import Redis, RedisError
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)

app = Flask(__name__)

@app.route("/")
def hello():
try:
visits = redis.incr("counter")
except RedisError:
visits = "<i>cannot connect to Redis, counter disabled</i>"

html = "<h3>Hello {name}!</h3>" \
"<b>Hostname:</b> {hostname}<br/>" \
"<b>Visits:</b> {visits}"
return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)

if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)

requirements.txt

1
2
Flask
Redis

根目录结构如下:

1
2
3
4
.
├── app.py
├── Dockerfile
└── requirements.txt

构建app

1
docker build --tag=friendlyhello .

运行app

1
docker run -p 4000:80 friendlyhello

以daemon模式运行

1
docker run -d -p 4000:80 friendlyhello

查看container信息

1
docker container ls

停止容器

1
docker container stop container-ID

container相关命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
docker build -t friendlyhello .  # Create image using this directory's Dockerfile
docker run -p 4000:80 friendlyhello # Run "friendlyhello" mapping port 4000 to 80
docker run -d -p 4000:80 friendlyhello # Same thing, but in detached mode
docker container ls # List all running containers
docker container ls -a # List all containers, even those not running
docker container stop <hash> # Gracefully stop the specified container
docker container kill <hash> # Force shutdown of the specified container
docker container rm <hash> # Remove specified container from this machine
docker container rm $(docker container ls -a -q) # Remove all containers
docker image ls -a # List all images on this machine
docker image rm <image id> # Remove specified image from this machine
docker image rm $(docker image ls -a -q) # Remove all images from this machine
docker login # Log in this CLI session using your Docker credentials
docker tag <image> username/repository:tag # Tag <image> for upload to registry
docker push username/repository:tag # Upload tagged image to registry
docker run username/repository:tag # Run image from a registry

Services

在分布式应用中,应用的不同部分被成为services。例如,想象一个video分享网站,它可能包含一个存储应用数据到数据库的一个服务,一个在后后台转码用户上传的数据,一个服务在前台等等。

Services就像成产环境中的containers。一个service仅仅运行一个image,但是它决定image如何运行——哪些端口可以使用,服务实现高可用所需要的副本个数等等。扩展一个服务改变运行那个软件所运行容器实例的个数,在进程中赋予更多计算资源给服务。

幸运的是这很容易去定义,执行和扩展services通过Docker平台–仅仅写一个docker-compose.yml文件。

docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
version: "3"
services:
web:
# replace username/repo:tag with your name and image details
image: username/repo:tag
deploy:
replicas: 5
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure
ports:
- "4000:80"
networks:
- webnet
networks:
webnet:

scrapy之爬虫暂停与恢复

发表于 2019-09-05

对于爬虫而言,如果能够设置断点,停止后恢复运行可以继续从上次中断的点开始运行,无疑是一个友好的特性,实现原理无非是将中断信息持久化,scrapy是实现这个这个特性的,然鹅在这里踩坑了。

Scrapy: Jobs pausing and resuming crawls

参考文档戳上面

按照文档中的操作,只需要在scrapy crawl spider_name -s JOBDIR=job_dir/xxx后面加上设置JOBDIR变量的参数即可,然后发送一个停止的信号即可。

可是遇到了这样的问题,在发送完一次停止信号之后,程序没停,然后又发送了一次,程序强制被停,重启之后显示如下

23:00:22 [scrapy.core.engine] INFO: Spider opened
1
2
3
4
2019-09-05 23:00:22 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2019-09-05 23:00:22 [scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:6023
2019-09-05 23:00:22 [scrapy.dupefilters] DEBUG: Filtered duplicate request: <GET https://www.privateproperty.com.ng/property-for-sale?sortby=listeddesc> (referer: None)
2019-09-05 23:00:22 [scrapy.core.engine] INFO: Closing spider (finished)

显示了一个filtered duplicate request之后就停止退出了,什么鬼?然后在搜索相关的问题,发现给出的都不是想要的答案,最后在stackoverflow上发现得分很低的答案。

1
If you click Ctrl+C twice (force stop) it won't be able to be continued. Click Ctrl+C just once and wait.

试着做了,果然发送一个信号后等程序停止了重新恢复后就可以继续运行。

上面说原理也就是保存断点的信息,对比一下强退和等待退出的目录结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
等待退出
|____requests.queue
| |____active.json
| |____p0
|____requests.seen
|____spider.state

强制退出
.
|____requests.queue
| |____p0
|____requests.seen
|____spider.state

可见在目录结构上是有差异的。至于根本原因,需要阅读源码之后再给出答案,后续更新。

python模拟登录

发表于 2019-07-07

想使用python requests库直接调用api,却又需要相关的Cookie信息,比如:session ID。此时就需要登录之后拿到Cookie信息,在发起http请求时候携带上Cookie,就可以访问其他api了。

使用selenium库模拟登录获取Cookie。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from selenium import webdriver

# remeber to call driver.close()
driver = webdriver.Chrome(executable_path='/usr/local/bin/hromedriver')

driver.get('www.xxx.com/login.html')

username_elem = driver.find_elements_by_id('username')
passwd_elem = driver.find_elements_by_id('passwd')

username_elem.clear()
passwd_elem.clear()

# input username
username_elem.send_keys('username')
# input passwd
passwd_elem.send_keys('passwd')

button_elem = driver.find_elements_by_button('button')
# submit form
button_elem.submit()

上述代码执行完,Cookie相关信息就保存在driver中。

1
2
3
4
5
6
7
8
9
10
11
import requests

request = requests.Session()

# retrive Cookie from driver
cookies = driver.get_cookies()

for cookie in cookies:
request.cookies.set(cookie['name'], cookie['value'])

request.get('http://www.xxx.com/api/xxx')

上面代码发送的请求中就会携带之前登录获取到的Cookie信息,这样就可以跳过被爬站点的认证,直接访问api。

Reference:

https://zhuanlan.zhihu.com/p/28587931

认证和授权

发表于 2019-07-05
  • 认证的目的是问了认出用户是谁。
  • 授权的目的是为了决定用户能够做什么。

认证实际上就是验证凭证的过程。凭证可以是钥匙、指纹、虹膜等。

如果只有一个凭证被用于认证,则称为单因素认证。

如果有两个或多个凭证被用于认证,则称为双因素(Two Factors)认证或多因素认证。

多因素认证的安全强度要高于单因素认证,但是在用户体验上,多因素认证会带来一些不方便的地方。

密码作为一种凭证,在存储时也需要注意一些问题。一般来说,密码必须以不可逆的加密算法,或者是单项散列函数算法,加密后存储到数据库中。这样做是为了尽最大可能地保证密码的私密性,即使是网站的管理人员,也不能够看到用户的密码。在这种情况下,黑客即使入侵了网站,导出数据库中的数据,也无法获取到密码的明文。

目前黑客们广泛使用的一种MD5加密的密码的方法是彩虹表。

彩虹表的思路是收集尽可能多的密码明文和明文对应的MD5值。这样只需要查询MD5值,就能够找到该MD5值对应的明文。一个好的彩虹表,可能会非常庞大,但这种方法确实有效。

为了避免密码哈希值泄露后,黑客能直接通过彩虹表查询出密码的明文,在计算密码明文的哈希值时,增加一个salt。salt是一个字符串,它的作用时为了增加明文的复杂度,并能使彩虹表一类的攻击失效。

salt的使用:MD5(username+passwd+salt)

salt应该保存在服务器端的配置文件中,并妥善保管。

Session与认证

密码与证书等认证手段,一般仅仅用于登录(Login)的过程。当登录完成后,用户访问网站页面,不能每次浏览器请求页面时都在使用密码认证一次。因此,当认证成功以后,需要替换一个对用户透明的凭证。这个凭证就是sessionID。

当用户登录完成后,在服务器端就会创建一个新的会话(Session),会话中会保存用户状态和相关信息。服务器端维护所有在线用户的Session,此时的认证,只需要知道是哪个用户在浏览当前页面即可。为了告诉服务器应该使用哪一个Session,浏览器需要把当前用户的Session ID告知服务器。

最常见的做法就是把sessionID加密后保存在Cookie中,因为Cookie会随着HTTP请求发送,且收到浏览器通源策略的保护。

Session一旦在生命周期内被劫持,就等同于账户失窃。同时由于SessionID是用户登录后才持有的认证凭证,因此黑客不需要再攻击登录过程(比如密码),在设计安全方案时需要意识到这单。

Session劫持就是一种通过窃取用户SessionID后,使用该SessionID登录进目标账户的攻击方法,此时攻击者实际上是使用了目标账户的有效Session。如果SessionID是保存在Cookie中的,则这种攻击可以称为Cookie劫持。

Cookie泄漏的方式有多种,最常见的有XSS攻击、网络Sniff,以及本地木马窃取,对于同构XSS漏洞窃取Cookie的攻击,通过给Cookie标记httponly,可以有效缓解XSS窃取Cookie的问题。但是其他泄露途径,比如网络嗅探或者Cookie文件失窃,则会涉及到客户端的环境安全,需要从用户客户端着手解决。

SessionID除了可以保存在Cookie中外,还可以保存在URL中,作为请求的一个参数,但是这种方式的安全性是难以经受考验的。

在生成SessionID时,需要保证足够的随机性,比如采用足够强的伪随机数生成算法。现在的网站开发中,都有很多成熟的开发框架可以使用。这些成熟的开发框架一般都会提供Cookie管理、Session管理的函数,可以善用这些函数和功能。

CGI, FastCGI, php-cgi, php-fpm的理解

发表于 2019-07-03

CGI

CGI是一种协议,CGI是一种协议,CGI是一种协议。

定义了web服务和外部应用之间的交互方式。

外部应用指不同语言编写的CGI脚本。

CGI脚本用来生成动态的页面内容。

CGI进程每次处理请求都要被初始化,处理完之后退出。

FastCGI

FastCGI是一种协议,FastCGI是一种协议,FastCGI是一种协议。

是对CGI的一种改进。

不需要每次请求处理完程序退出,下次请求来了可以直接复用该进程。

php-cgi

php-cgi解析cgi协议数据,调用php的php_execute_script函数来解析和运行php文件。

php-fpm

php-fpm是一个fastcgi进程管理器,类似于连接池,用于管理与web服务器的连接,而fastcgi协议的解析是通过php-fcgi进行解析的,之后将php文件交给php_execute_script函数来执行。

参考:

https://www.basezap.com/difference-php-cgi-php-fpm/

https://help.superhosting.bg/en/cgi-common-gateway-interface-fastcgi.html

https://www.zhihu.com/question/268732467

php基本语法

发表于 2019-07-03

php脚本以<?php>开始,以<?>结束,可以放在文档中的任何位置。

  • 变量
  • 数组
  • 函数
  • 控制结构
  • 注释

变量

规则:

  • 变量以$符号开始,后面跟着变量的名称
  • 变量名以不能以数字开头
  • 变量名只能包含数字,字母以及下划线
  • 变量名区分大小写

定义变量a

1
$a = 10;

数组

创建数组person

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 数值数组
$person = array("student", "doctor", "worker");

echo $person[0]
echo $person[1]
echo $person[2]

// 关联数组
$person = array("student"=>"Cruise", "doctor"=>"Kobe", "worker"=>"James");

echo $person["student"];

// 遍历关联数组
foreach($person as $x=>$x_value)
{
echo "key=" . %x . ", value=" . $x_value;
}

函数

定义函数f

1
2
3
4
function f() 
{
// code
}

带参数的函数

1
2
3
4
function f($a)
{
echo $a;
}

带有返回值

1
2
3
4
function f($a, $b)
{
return $a + $b;
}

控制结构


For循环

1
2
3
4
5
6
7
8
9
for ($i = 1; $i <= 5; $i++)
{
echo "The number is " . $i;
}

foreach ($x as $value)
{
echo $value;
}

While循环

1
2
3
4
5
while ($i <= 5)
{
echo $i;
$i++;
}

Do while语句

1
2
3
4
5
do
{
echo $i;
$i++;
} while ($i < 5)

If语句

1
2
3
4
5
6
7
8
if ($t < 20)
{
echo "Have a good day";
} elseif {
echo "Have a bad day";
} else {
echo "Boom";
}

Switch语句

1
2
3
4
5
6
7
8
9
10
11
switch ($n) 
{
case "red":
echo "red";
break;
case "blue":
echo "blue";
break;
default:
echo "default";
}

注释


行注释://, #
块注释:/* */

链接的接口——符号

发表于 2019-06-28

链接的本质就是将多个目标文件拼接到一起形成可执行文件。为了使不同的目标文件之间能够拼接,必须有一定的规则才行,就像协议一样。在链接中,目标文件之前的相互拼接实际上是目标文件之间对地址的引用,即对函数和变量的地址的引用。比如目标文件B用到了目标文件A中的函数foo,就称目标文件A定义了函数foo,目标文件B引用了目标文件A中的函数foo。在链接中,我们将函数和变量统称为符号,函数名或变量名就是符号名。

整个链接的过程正是基于符号才能够正确完成。链接过程中很关键的一部分就是符号管理,每一个目标文件都会有一个相应的符号表,这个表里记录了目标文件中所用到的所有符号。每个定义的符号有一个对应的值,叫做符号值,对于变量和函数来说,符号值就是他们的地址。

符号表中的分类:

  • 定义在本目标文件中的全局符号,可以被其他目标文件引用。
  • 在本目标文件中引用的全局符号,却没有定义在本目标文件。
  • 段名,这种符号往往由编译器产生,它的值就是该段的起始地址。
  • 局部符号,这类符号只在编译单元内部可见。这些局部符号对于链接过程没有作用,链接器往往忽略它们。
  • 行号信息,即目标文件指令与源代码中代码行的对应关系,它也是可选的。

对于我们来说,最值得关注的就是全局符号,即上面分类中的第一类和第二类。因为链接过程只关心全局符号相互黏合,局部符号、段名、行号都是次要的,它们对于其他目标文件来说是不可见的,在链接过程中也是无关紧要的。

魔数的由来

发表于 2019-06-27

a.out格式的魔数为0x01、0x07,为什么会规定这个魔数呢?

Unix早年是在PDP小型机上诞生的,当时的系统在加载一个可执行文件后直接从文件的第一个字节开始执行,人们一般在文件的最开始位置放一条跳转(jump)指令,这条指令负责跳过接下来的7个机器字的头文件到可执行文件的真正入口。而0x01 0x07这两个字节刚好是当时PDP-11的机器的跳转7个机器字的指令。为了跟以前的系统保持兼容性,这条跳转指令被当作魔数一直保留到了几十年后的今天。

BSS段不占磁盘空间的理解

发表于 2019-06-27

BSS段存放两种变量类型:

  • 未初始化全局变量
  • 未初始化局部静态变量

如何证明BSS段不占磁盘空间?

  • 其他各段数据不变,单纯增加BSS段存放的变量,观察ELF文件大小的变化

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    > echo 'int global[1024]; int main() { return 0; }' > test.c
    > gcc test.c -o test
    > ls -rtl test
    ----------------
    -rwxrwxr-x 1 cruise cruise 4569 6月 26 23:21 test
    ----------------

    > size test
    ----------------
    text data bss dec hex filename
    960 248 4128 5336 14d8 test
    ----------------

    // 将global大小扩大一倍
    > echo 'int global[2048]; int main() { return 0; }' > test.c
    > gcc test.c -o test
    > ls -rtl test
    ---------------
    -rwxrwxr-x 1 cruise cruise 4569 6月 26 23:25 test
    ---------------

    > size test
    --------------
    text data bss dec hex filename
    960 248 8224 9432 24d8 test
    --------------

    将global数组的大小增加一倍的时候,文件的大小仍然不变。

  • 对BSS段中的变量进行初始化,变量将被存放在数据段,观察ELF文件大小的变化

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    > echo 'int global[1024]; int main() { return 0; }' > test.c
    > gcc test.c -o test
    > ls -rtl test
    ----------------
    -rwxrwxr-x 1 cruise cruise 4569 6月 26 23:21 test
    ----------------

    > size test
    ----------------
    text data bss dec hex filename
    960 248 4128 5336 14d8 test
    ----------------

    // 将对global进行初始化
    > echo 'int global[1024] = {1}; int main() { return 0; }' > test.c
    > gcc test.c -o test
    > ls -rtl test
    ----------------
    -rwxrwxr-x 1 cruise cruise 8701 6月 26 23:39 test
    ----------------

    > size test
    ----------------
    text data bss dec hex filename
    960 4372 8 5340 14dc test
    ----------------

    将global进行初始化之后,ELF文件增大将近一倍。而如果BSS段占用磁盘空间的话,大小不变才对。

通过上面两个实验可以证明,BSS段实际是不占用磁盘空间的,只在段表中记录大小,在符号表中记录符号。当文件装载运行时,才会分配空间以及初始化。

BSS历史

BSS(Block Started by Symbol)这个词最初是UA-SAP汇编器(United Aircraft Symbolic Assembly Program)中的一个伪指令,用于为符号预留一块内存空间。该汇编起由美国联合航空公司于20世纪50年代中期为IBM 704大型机所开发。

后来BSS这个词被作为关键子引入到IBM 709和7090/94机器上的汇编器FAP(Fortran Assembly Program),用于定义符号并且为该符号预留给定数量的未初始化空间。

Unix FAQ session 1.3( http://www.faqs.org/faqs/unix-faq/faq/part1/section-3.html)里面有Unix和C语言之父Dennis Rithcie对BSS这个词由来的解释。

-- 摘自《程序员的自我修养——链接、装载与库》

objdump

发表于 2019-06-26

objdump命令

显示目标文件的信息

选项

1
Usage: objdump <option(s)> <file(s)>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-a 
--archive-headers
显示静态库文件的头信息,包含组成静态库的目标文件

> objdump -a test.a
----------------
In archive libtest.a:

a.o: file format elf32-i386
rw-rw-r-- 500/501 812 Jun 25 22:42 2019 a.o


b.o: file format elf32-i386
rw-rw-r-- 500/501 753 Jun 25 22:44 2019 b.o
-----------------
1
2
3
4
5
6
7
8
9
10
11
-f
--file-headers
文件头,描述整个文件的文件属性,包括是否可执行、是否重定向、是静态链接还是动态链接以及入口地址(如果是可执行文件)、目标硬件、目标操作系统等信息

> objdump -f test.o
------------------
test.o: file format elf32-i386
architecture: i386, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x00000000
------------------
1
2
3
-p
--private-headers
显示目标文件格式详细的信息,与目标文件格式相关。对于某些目标文件格式,没有额外的信息被打印。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
-h
--[section-]headers
显示各个段的头部摘要信息

> objdump -h test.o
------------------
test.o: file format elf32-i386

Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000027 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 00000000 00000000 0000005c 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 0000005c 2**2
ALLOC
3 .comment 0000002e 00000000 00000000 0000005c 2**0
CONTENTS, READONLY
4 .note.GNU-stack 00000000 00000000 00000000 0000008a 2**0
CONTENTS, READONLY
-----------------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
-x
--all-headers
显示所有可用的头部信息,包括符号表和重定位入口

> objdump -x test.o
-----------------
test.o: file format elf32-i386
test.o
architecture: i386, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x00000000

Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000027 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 00000000 00000000 0000005c 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 0000005c 2**2
ALLOC
3 .comment 0000002e 00000000 00000000 0000005c 2**0
CONTENTS, READONLY
4 .note.GNU-stack 00000000 00000000 00000000 0000008a 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00000000 l df *ABS* 00000000 a.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .note.GNU-stack 00000000 .note.GNU-stack
00000000 l d .comment 00000000 .comment
00000000 g F .text 00000027 main
00000000 *UND* 00000000 shared
00000000 *UND* 00000000 swap


RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
00000015 R_386_32 shared
00000021 R_386_PC32 swap
--------------------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-d
--disassemble
反汇编可执行段

> objdump -d test.o
-------------------
test.o: file format elf32-i386


Disassembly of section .text:

00000000 <main>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 e4 f0 and $0xfffffff0,%esp
6: 83 ec 20 sub $0x20,%esp
9: c7 44 24 1c 64 00 00 movl $0x64,0x1c(%esp)
10: 00
11: c7 44 24 04 00 00 00 movl $0x0,0x4(%esp)
18: 00
19: 8d 44 24 1c lea 0x1c(%esp),%eax
1d: 89 04 24 mov %eax,(%esp)
20: e8 fc ff ff ff call 21 <main+0x21>
25: c9 leave
26: c3 ret
------------------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
-D
--disassemble-all
反汇编所有段

> objdump -D test.o
test.o: file format elf32-i386


Disassembly of section .text:

00000000 <main>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 e4 f0 and $0xfffffff0,%esp
6: 83 ec 20 sub $0x20,%esp
9: c7 44 24 1c 64 00 00 movl $0x64,0x1c(%esp)
10: 00
11: c7 44 24 04 00 00 00 movl $0x0,0x4(%esp)
18: 00
19: 8d 44 24 1c lea 0x1c(%esp),%eax
1d: 89 04 24 mov %eax,(%esp)
20: e8 fc ff ff ff call 21 <main+0x21>
25: c9 leave
26: c3 ret

Disassembly of section .comment:

00000000 <.comment>:
0: 00 47 43 add %al,0x43(%edi)
3: 43 inc %ebx
4: 3a 20 cmp (%eax),%ah
6: 28 47 4e sub %al,0x4e(%edi)
9: 55 push %ebp
a: 29 20 sub %esp,(%eax)
c: 34 2e xor $0x2e,%al
e: 34 2e xor $0x2e,%al
10: 37 aaa
11: 20 32 and %dh,(%edx)
13: 30 31 xor %dh,(%ecx)
15: 32 30 xor (%eax),%dh
17: 33 31 xor (%ecx),%esi
19: 33 20 xor (%eax),%esp
1b: 28 52 65 sub %dl,0x65(%edx)
1e: 64 20 48 61 and %cl,%fs:0x61(%eax)
22: 74 20 je 44 <main+0x44>
24: 34 2e xor $0x2e,%al
26: 34 2e xor $0x2e,%al
28: 37 aaa
29: 2d 32 33 29 00 sub $0x293332,%eax
------------------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  -S
--source
同时显示汇编代码和源码,编译时指定-g选项时

> objdump -S test.o
------------------
test.o: file format elf32-i386


Disassembly of section .text:

00000000 <main>:
/* a.c */
extern int shared;

int main()
{
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 e4 f0 and $0xfffffff0,%esp
6: 83 ec 20 sub $0x20,%esp
int a = 100;
9: c7 44 24 1c 64 00 00 movl $0x64,0x1c(%esp)
10: 00
swap( &a, &shared );
11: c7 44 24 04 00 00 00 movl $0x0,0x4(%esp)
18: 00
19: 8d 44 24 1c lea 0x1c(%esp),%eax
1d: 89 04 24 mov %eax,(%esp)
20: e8 fc ff ff ff call 21 <main+0x21>
}
25: c9 leave
26: c3 ret
------------------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  -s
--full-contents
显示所有段的详细内容

> objdump -s test.o
------------------
test.o: file format elf32-i386

Contents of section .text:
0000 5589e583 e4f083ec 20c74424 1c640000 U....... .D$.d..
0010 00c74424 04000000 008d4424 1c890424 ..D$......D$...$
0020 e8fcffff ffc9c3 .......
Contents of section .debug_abbrev:
0000 01110125 0e130b03 081b0e11 01120110 ...%............
0010 06000002 2e013f0c 030e3a0b 3b0b4913 ......?...:.;.I.
0020 11011201 400a0113 00000334 0003083a ....@......4...:
0030 0b3b0b49 13020a00 00042e01 3f0c030e .;.I........?...
0040 3a0b3b0b 49133c0c 00000518 00000006 :.;.I.<.........
0050 24000b0b 3e0b0308 00000734 00030e3a $...>......4...:
0060 0b3b0b49 133f0c3c 0c000000 .;.I.?.<....
Contents of section .debug_info:
0000 79000000 03000000 00000401 00000000 y...............
0010 01612e63 00390000 00000000 00270000 .a.c.9.......'..
0020 00000000 00020134 00000001 045b0000 .......4.....[..
0030 00000000 00270000 00019c5b 00000003 .....'.....[....
0040 61000106 5b000000 02741c04 012f0000 a...[....t.../..
0050 0001075b 00000001 05000006 0405696e ...[..........in
0060 74000728 00000001 025b0000 00010107 t..(.....[......
0070 28000000 01025b00 00000101 00 (.....[......
Contents of section .debug_line:
0000 31000000 02001a00 00000101 fb0e0d00 1...............
0010 01010101 00000001 00000100 612e6300 ............a.c.
0020 00000000 00050200 00000016 9183083d ...............=
0030 02020001 01 .....
Contents of section .debug_pubnames:
0000 17000000 02000000 00007d00 00002500 ..........}...%.
0010 00006d61 696e0000 000000 ..main.....
Contents of section .debug_aranges:
0000 1c000000 02000000 00000400 00000000 ................
0010 00000000 27000000 00000000 00000000 ....'...........
Contents of section .debug_str:
0000 474e5520 4320342e 342e3720 32303132 GNU C 4.4.7 2012
0010 30333133 20285265 64204861 7420342e 0313 (Red Hat 4.
0020 342e372d 32332900 73686172 65640073 4.7-23).shared.s
0030 77617000 6d61696e 002f686f 6d652f63 wap.main./home/c
0040 72756973 652f636c 616e6700 ruise/clang.
Contents of section .comment:
0000 00474343 3a202847 4e552920 342e342e .GCC: (GNU) 4.4.
0010 37203230 31323033 31332028 52656420 7 20120313 (Red
0020 48617420 342e342e 372d3233 2900 Hat 4.4.7-23).
Contents of section .debug_frame:
0000 10000000 ffffffff 0100017c 080c0404 ...........|....
0010 88010000 1c000000 00000000 00000000 ................
0020 27000000 410e0885 02420d05 63c50c04 '...A....B..c...
0030 04000000 ....
----------------
1
2
3
-g
--debugging
显示调试信息
1
2
3
-e
--debugging-tags
类似与-g选项,生成的是和ctags工具相兼容的信息
1
2
3
-G
--stabs
显示文件中任何STABS信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-t
--syms
显示符号表的内容

> objdump -t test.o
---------------------
test.o: file format elf32-i386

SYMBOL TABLE:
00000000 l df *ABS* 00000000 a.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .debug_abbrev 00000000 .debug_abbrev
00000000 l d .debug_info 00000000 .debug_info
00000000 l d .debug_line 00000000 .debug_line
00000000 l d .debug_pubnames 00000000 .debug_pubnames
00000000 l d .debug_aranges 00000000 .debug_aranges
00000000 l d .debug_str 00000000 .debug_str
00000000 l d .note.GNU-stack 00000000 .note.GNU-stack
00000000 l d .debug_frame 00000000 .debug_frame
00000000 l d .comment 00000000 .comment
00000000 g F .text 00000027 main
00000000 *UND* 00000000 shared
00000000 *UND* 00000000 swap
---------------------
1
2
3
4
5
6
7
8
9
10
11
12
-T
--dynamic-syms
显示动态符号表的内容

> objdump -T test.o
----------------------
test.o: file format elf32-i386

objdump: test.o: not a dynamic object
DYNAMIC SYMBOL TABLE:
no symbols
----------------------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
-r
--reloc
显示重定位的入口,可以和-d, -D 配合使用

> objdump -r test.o
----------------------
test.o: file format elf32-i386

RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
00000015 R_386_32 shared
00000021 R_386_PC32 swap


RELOCATION RECORDS FOR [.debug_info]:
OFFSET TYPE VALUE
00000006 R_386_32 .debug_abbrev
0000000c R_386_32 .debug_str
00000015 R_386_32 .debug_str
00000019 R_386_32 .text
0000001d R_386_32 .text
00000021 R_386_32 .debug_line
00000027 R_386_32 .debug_str
00000031 R_386_32 .text
00000035 R_386_32 .text
0000004d R_386_32 .debug_str
00000063 R_386_32 .debug_str
00000070 R_386_32 .debug_str


RELOCATION RECORDS FOR [.debug_line]:
OFFSET TYPE VALUE
00000027 R_386_32 .text


RELOCATION RECORDS FOR [.debug_pubnames]:
OFFSET TYPE VALUE
00000006 R_386_32 .debug_info


RELOCATION RECORDS FOR [.debug_aranges]:
OFFSET TYPE VALUE
00000006 R_386_32 .debug_info
00000010 R_386_32 .text


RELOCATION RECORDS FOR [.debug_frame]:
OFFSET TYPE VALUE
00000018 R_386_32 .debug_frame
0000001c R_386_32 .text
----------------------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
-R
--dynamic-reloc
显示动态重定位的入口

> objdump -R /lib/ld-2.12.so
---------------------
/lib/ld-2.12.so: file format elf32-i386

DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
0001fe08 R_386_RELATIVE *ABS*
0001fe14 R_386_RELATIVE *ABS*
0001fe18 R_386_RELATIVE *ABS*
0001fe1c R_386_RELATIVE *ABS*
0001fe20 R_386_RELATIVE *ABS*
0001fe24 R_386_RELATIVE *ABS*
0001fe28 R_386_RELATIVE *ABS*
0001fe2c R_386_RELATIVE *ABS*
0001fe30 R_386_RELATIVE *ABS*
0001fe34 R_386_RELATIVE *ABS*
0001fe38 R_386_RELATIVE *ABS*
0001ffe8 R_386_RELATIVE *ABS*
0001fff4 R_386_RELATIVE *ABS*
00020834 R_386_RELATIVE *ABS*
0001ffec R_386_GLOB_DAT __libc_enable_secure
0001fff0 R_386_GLOB_DAT _r_debug
0001fff8 R_386_GLOB_DAT free
0001ffd0 R_386_JUMP_SLOT __libc_memalign
0001ffd4 R_386_JUMP_SLOT malloc
0001ffd8 R_386_JUMP_SLOT calloc
0001ffdc R_386_JUMP_SLOT realloc
0001ffe0 R_386_JUMP_SLOT ___tls_get_addr
0001ffe4 R_386_JUMP_SLOT free
---------------------
1
2
@file
从文件中读取选项
1
2
3
4
5
6
7
8
9
10
11
12
-v
--version
显示程序的版本号

> objdump -v
--------------------
GNU objdump version 2.20.51.0.2-5.48.el6 20100205
Copyright 2009 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) any later version.
This program has absolutely no warranty.
---------------------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
-i
--info
列出支持的目标格式和架构

> objdump -i
---------------------
BFD header file version version 2.20.51.0.2-5.48.el6 20100205
elf32-i386
(header little endian, data little endian)
i386
a.out-i386-linux
(header little endian, data little endian)
i386
pei-i386
(header little endian, data little endian)
i386
elf64-x86-64
(header little endian, data little endian)
i386
elf64-l1om
(header little endian, data little endian)
l1om
elf64-little
(header little endian, data little endian)
i386
l1om
elf64-big
(header big endian, data big endian)
i386
l1om
elf32-little
(header little endian, data little endian)
i386
l1om
elf32-big
(header big endian, data big endian)
i386
l1om
srec
(header endianness unknown, data endianness unknown)
i386
l1om
symbolsrec
(header endianness unknown, data endianness unknown)
i386
l1om
verilog
(header endianness unknown, data endianness unknown)
i386
l1om
tekhex
(header endianness unknown, data endianness unknown)
i386
l1om
binary
(header endianness unknown, data endianness unknown)
i386
l1om
ihex
(header endianness unknown, data endianness unknown)
i386
l1om
trad-core
(header endianness unknown, data endianness unknown)

elf32-i386 a.out-i386-linux pei-i386 elf64-x86-64 elf64-l1om
i386 elf32-i386 a.out-i386-linux pei-i386 elf64-x86-64 ----------
l1om ---------- ---------------- -------- ------------ elf64-l1om

elf64-little elf64-big elf32-little elf32-big srec symbolsrec
i386 elf64-little elf64-big elf32-little elf32-big srec symbolsrec
l1om elf64-little elf64-big elf32-little elf32-big srec symbolsrec

verilog tekhex binary ihex trad-core
i386 verilog tekhex binary ihex ---------
l1om verilog tekhex binary ihex ---------
---------------------
12

Cruise

记录岁月。

11 日志
© 2019 Cruise
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4