59 多次 mmap 虚拟地址的关系

前言

这是来自于网友的一篇帖子 

然后 我们这里来探究一下这个问题

主要是 多次连续的 mmap 获取到的 虚拟地址区域 是否连续

以及 衍生出的一些其他的问题

从 mmap 的实现 我们可以知道, mmap 的空间是 自顶向下 分配的, 因此 两块空间应该是连续的, 第一块在上面, 第二块在下面 

 

 

测试用例

测试用例很简单, 就是多次 mmap 同一个文件, 然后 观察一下 其地址信息

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>

#define LEN (10*4096)

int main(void) {
    int fd;
    char *vadr;

    if ((fd = open("./1.txt", O_RDWR)) < 0) {
        return 0;
    }
    vadr = mmap(0, LEN, PROT_READ, MAP_PRIVATE | MAP_LOCKED, fd, 0);
    printf("vaddr = 0x%x\n", vadr);
    printf(" ch = %c \n", vadr[10]);


    if ((fd = open("./1.txt", O_RDWR)) < 0) {
        return 0;
    }
    vadr = mmap(0, LEN, PROT_READ, MAP_PRIVATE | MAP_LOCKED, fd, 0);
    printf("vaddr = 0x%x\n", vadr);
    printf(" ch = %c \n", vadr[10]);

    return 0;
}

 

程序执行输出如下, 可以证实我们上面的猜想, 但是还有一些 细节我们需要去了解

root@ubuntu:~/Desktop/linux/HelloWorld# ./startGdbServer.sh
Test07MmapRead.c: In function ‘main’:
Test07MmapRead.c:19:12: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘char *’ [-Wformat=]
     printf("vaddr = 0x%x\n", vadr);
            ^
Test07MmapRead.c:27:12: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘char *’ [-Wformat=]
     printf("vaddr = 0x%x\n", vadr);
            ^
Process /root/Desktop/linux/HelloWorld/Test07MmapRead created; pid = 52114
Listening on port 1235
Remote debugging from host ::ffff:192.168.220.132, port 44444
vaddr = 0xf7fea000
 ch = f
vaddr = 0xf7fe0000
 ch = f

 

 

基于内核的调试多次 mmap 的调用

我们这里 先放出一部分调试结果信息作为参照

如下调试会分为两个部分, 一个是 内核的调试, 一个是 glibc的调试, 这两部分 完整的解释日志的信息

我们这里核心关注的是 1.txt 对应的两段空间, 以及其到 堆栈底部 的空间

所以 ld-2.23.so, libc-2.23.so 对应的空间应该是 mmap 映射了之后 进行了 munmap 因此才有如下奇怪的 mmap 空间的申请, 然后 我们这里需要 大致梳理清楚 如下日志的具体情况

2260992 - 0x228000 - 0x7ffff7dd7000 - 0x7ffff7fff000 - ld-2.23.so
16384 - 0x4000 - 0x7ffff7ff8000 - vdso_image
4096 - 0x1000 - 0x7ffff7ff7000 - system_dirs
4096 - 0x1000 - 0x7ffff7ff6000 - realname libc.so.6 
3973120 - 0x3ca000 - 0x7ffff7a00000 - libc-2.23.so
	0x7ffff7dcf000 - dl_main - openaux - dl_map_segments 
	0x7ffff7dd5000 - dl_main - openaux - dl_map_segments
4096 - 0x1000 - 0x7ffff7ff5000 - dl_main - init_tls - dl_allocate_tls_storage - libc_memalign 
4096 - 0x1000 - 0x7ffff7ff4000 - dl_main - init_tls - dl_allocate_tls_storage - allocate_dtv 
40960 - 0xa000 - 0x7ffff7fea000 - 1.txt
40960 - 0xa000 - 0x7ffff7fe0000 - 1.txt

 

第一个 mmap 调用如下, 主要是 加载 ld-2.23.so, 这个纯粹是在内核的调用, 所以 待会儿 glibc 的调试不会碰到它 

ld-2.23.so 文件大小接近 160kb 左右  

83077a8059544ed5a28adf481c2d58bd.png

 

接着 munmap 了没有使用的空间, 现在的情况是 ld-2.23.so 占用的空间是 0x7ffff7dd7000 - 0x7ffff7dfd000

释放掉了空间 0x7ffff7dfd000 - 0x7ffff7fff000

276462568b51466c86fcb057b46981c3.png 

第二个 mmap 调用如下,映射的是 vdso 的镜像, 映射的区间是 0x7ffff7ff8000 - 0x7ffff7ffc000

f6e7edd503414a0f94d61b9afac1942e.png

 

第三个 mmap 调用如下, 映射的是 “/root/Desktop/linux/glibc-2.23/install/lib” 的字符串, 映射的区间是 0x7ffff7ff7000 - 0x7ffff7ff8000

9046882641c144f3a3d002a421dec579.png

 

第四个 mmap 调用如下, 映射的是 “libc.so.6” 对应的一个 linkmap 的一个结构体, 映射的区间是 0x7ffff7ff6000 - 0x7ffff7ff7000

0f66c4bbb66c4ac8a05b48e61d3b6ab0.png

 

第五个 mmap 调用如下,映射的是 “libc-2.23.so” 的动态库, 映射的区间是 0x7ffff7a0d000 - 0x7ffff7dd7000

空间之所以 在这里是因为 ld-2.23.so 的 mmap 映射区只有 2m, 这里需要 3m, 因此 继续向前寻找空间, 找到的 ld-2.23.so 前面的一块空间 

cf3c7714d06d4b9c98fbfa7b68458e48.png

 

第六个 mmap 调用如下, dl_main - init_tls - dl_allocate_tls_storage - libc_memalign 映射了 4k 的映射区, 映射的区间是 0x7ffff7ff5000 - 0x7ffff7ff6000

6310225c1fa345859860209bd7371455.png 

第七个 mmap 调用如下, dl_main - init_tls - dl_allocate_tls_storage - allocate_dtv 映射了 4k 的映射区, 映射的区间是 0x7ffff7ff4000 - 0x7ffff7ff5000

737a2b7830594dc4ac983dfe83808672.png 

 

接下来就是我们需要关心的业务 mmap 映射了 

目前 mmap 映射区已经使用的空间如下, 接着需要申请两个 40kb 的空间, 在 0x7ffff7dfd000 - 0x7ffff7ff4000 的空间是可以容纳这需求的 2 * 40kb 的 

0x7ffff7a0d000 - 0x7ffff7dd7000 = libc-2.23.so
0x7ffff7dd7000 - 0x7ffff7dfd000 = ld-2.23.so
0x7ffff7ff4000 - 0x7ffff7ff5000 = dl_main - init_tls - dl_allocate_tls_storage - allocate_dtv
0x7ffff7ff5000 - 0x7ffff7ff6000 = dl_main - init_tls - dl_allocate_tls_storage - libc_memalign
0x7ffff7ff6000 - 0x7ffff7ff7000 = system_dirs
0x7ffff7ff7000 - 0x7ffff7ff8000 = realname libc.so.6
0x7ffff7ff8000 - 0x7ffff7ffc000 = vdso_image

 

第八个 mmap 调用申请了 40kb, 申请的空间为 0x7ffff7fea000 - 0x7ffff7ff4000

16744318c95245e7849ba590c3a8d326.png

 

第九个 mmap 调用申请了 40kb, 申请的空间为 0x7ffff7fe0000 - 0x7ffff7fea000

4b42d959b5894999b726b2b3f5939d96.png 

 

最终整个 mmap 映射区使用空间如下  

0x7ffff7a0d000 - 0x7ffff7dd7000 = libc-2.23.so
0x7ffff7dd7000 - 0x7ffff7dfd000 = ld-2.23.so
0x7ffff7fe0000 - 0x7ffff7fea000 = mmap("1.txt")
0x7ffff7fea000 - 0x7ffff7ff4000 = mmap("1.txt")
0x7ffff7ff4000 - 0x7ffff7ff5000 = dl_main - init_tls - dl_allocate_tls_storage - allocate_dtv 
0x7ffff7ff5000 - 0x7ffff7ff6000 = dl_main - init_tls - dl_allocate_tls_storage - libc_memalign 
0x7ffff7ff6000 - 0x7ffff7ff7000 = system_dirs 
0x7ffff7ff7000 - 0x7ffff7ff8000 = realname libc.so.6 
0x7ffff7ff8000 - 0x7ffff7ffc000 = vdso_image

 

 

基于glibc的调试多次 mmap 的调用

这里主要是基于 glibc 进行调试, 这里的断点是上面的 内核调试断点的一部分

然后 上面各个 mmap 映射区的 大部分映射空间的逻辑意义 也可以在这里找到, 上面给出了各个 mmap 映射区的逻辑意义信息, 但是没有给为什么 

这里 基于 glibc 的调试就是 给出为什么 

 

第一个 mmap 调用如下, 映射的是 “/root/Desktop/linux/glibc-2.23/install/lib” 的字符串, 映射的区间是 0x7ffff7ff7000 - 0x7ffff7ff8000

4a825416b1914a9bb1191472087958d4.png

 

分配空间的大小参照, 以及具体使用如下, 注意这里的 malloc 不同于我们不同的应用程序的 malloc 调用

fae71955ff464bdd9291f3e6321215dc.png

 

第二个 mmap 调用如下,映射的是 “libc.so.6” 对应的一个 linkmap 的一个结构体, 映射的区间是 0x7ffff7ff6000 - 0x7ffff7ff7000

972885a97ec641dca07e4271fdcc8611.png

 

分配空间的大小参照, 以及具体使用如下, 主要是新建了一个 linkmap 结构体, 然后存储它的各个属性 

08e405dcb5684d3f844941b8f17d7f14.png  

第三个 mmap 调用如下,映射的是 “libc-2.23.so” 的动态库, 映射的区间是 0x7ffff7a38000 - 0x7ffff7dd7000

因为在宿主机 和 在 qemu 虚拟机中 libc-2.23.so 大小不太一样, 因此这里 libc-2.23.so 对应的 vma 区间不太一致 

50067e952d4440e7a18a0fde02314179.png

 

第四个 mmap 调用如下, 这里我们不太关心, 直接跳过 

内核中没有该断点, 因为这里是传入的地址, 内核的断点是在 申请空间的地方

a5c4eaad61444992b9ff5b96ea8e7e34.png

 

第五个 mmap 调用如下, 这里我们不太关心, 直接跳过 

内核中没有该断点, 因为这里是传入的地址, 内核的断点是在 申请空间的地方

7277b67bda764e74a7961e2ab7884a44.png

 

第六个 mmap 调用如下, dl_main - init_tls - dl_allocate_tls_storage - libc_memalign 映射了 4k 的映射区, 映射的区间是 0x7ffff7ff5000 - 0x7ffff7ff6000

ce72e0d0996147adbf844a368a229610.png

 

第七个 mmap 调用如下, dl_main - init_tls - dl_allocate_tls_storage - allocate_dtv 映射了 4k 的映射区, 映射的区间是 0x7ffff7ff4000 - 0x7ffff7ff5000

2786ddaca9e048e4b83aa79b25d53612.png

 

第八个 mmap 调用申请了 40kb, 申请的空间为 0x7ffff7fea000 - 0x7ffff7ff4000

从 rax 寄存器中可以看到 mmap 申请的空间的首地址, 从上层堆栈信息中可以看到当前执行的代码位置 

a1192f7d97de413e8676211ddbd98cc6.png

 

第九个 mmap 调用申请了 40kb, 申请的空间为 0x7ffff7fea000 - 0x7ffff7fe0000

从 rax 寄存器中可以看到 mmap 申请的空间的首地址, 从上层堆栈信息中可以看到当前执行的代码位置 

4fd5801c44fe4638836d44dcb2d29ba5.png

 

 

 main 中 第一个 mmap 和 第二个 mmap 调用如下, 你也可以对一下 上面 glibc 上层调用 mmap 的代码的地址信息 

809febbf94624237bcdf9f5131da7821.png

84256796d7934c279d0ccb3ba2419550.png 

 

同一个文件, 两个虚拟地址空间怎么关联的?

虚拟地址空间映射物理页的时候是从 pagecache 中获取的 给定的文件对应的物理页

两个虚拟地址空间 对应的文件一样, 因此是映射到了相同的物理页 

b6deb44adfea42388c8667b6812d9a11.png

 

第一个 mmap 映射区的第一个物理页如下 

0ac3a169640e4e40898f0fc7ce32c367.png

 

第二个 mmap 映射区的第一个物理页如下, 可以发现 两个虚拟地址空间映射的物理页相同

f69c98d2ce064193acc9dd2a0dbfa5bc.png

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/641723.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

solidworks画螺母学习笔记

螺母 单位mm 六边形 直径16mm&#xff0c;水平约束&#xff0c;内圆直径10mm 拉伸 选择两侧对称&#xff0c;厚度7mm 拉伸切除 画相切圆 切除深度7mm&#xff0c;反向切除 拔模角度45 镜像切除 倒角 直径1mm 异形孔向导 螺纹线 偏移打勾&#xff0c;距离为2mm…

开源的在线JSON数据可视化编辑器jsoncrack本地部署与远程访问

文章目录 1. 在Linux上使用Docker安装JSONCrack2. 安装Cpolar内网穿透工具3. 配置JSON Crack界面公网地址4. 远程访问 JSONCrack 界面5. 固定 JSONCrack公网地址 JSON Crack 是一款免费的开源数据可视化应用程序&#xff0c;能够将 JSON、YAML、XML、CSV 等数据格式可视化为交互…

Jmeter预习第1天

Jmeter参数化&#xff08;重点&#xff09; 本质&#xff1a;使用参数的方式来替代脚本中的固定为测试数据 实现方式&#xff1a; 定义变量&#xff08;最基础&#xff09; 文件定义的方式&#xff08;所有测试数据都是固定的情况下[死数据]&#xff0c;eg:注册登录&#xff0…

释放Mac潜能,选择Magic Disk Cleaner for Mac

想要让Mac运行更加流畅、性能更加出色吗&#xff1f;那就选择Magic Disk Cleaner for Mac吧&#xff01; Magic Disk Cleaner for Mac v2.7.7激活版下载 这款软件是Mac用户的得力助手&#xff0c;它拥有强大的扫描和清理功能&#xff0c;能够迅速找出并删除硬盘上的无用文件和垃…

智慧校园的建设思路

智慧校园建设的一个主要目的就是要打破学校内的信息孤岛&#xff0c;其核心是在人、流程和信息三个层面的全面整合。智慧校园应该能够为全校师生员工及校外用户提供统一的、一站式的服务渠道&#xff1b;能够将学校各种业务流程连接起来&#xff0c;实现各种应用系统的互联互通…

MySQL 带游标的存储过程(实验报告)

一、实验名称&#xff1a; 带游标的存储过程 二、实验日期&#xff1a; 2024 年 5月 25 日 三、实验目的&#xff1a; 掌握MySQL带游标的存储过程的创建及调用&#xff1b; 四、实验用的仪器和材料&#xff1a; 硬件&#xff1a;PC电脑一台&#xff1b; 配置&#xff1…

初出茅庐的小李博客之用MQTT.fx软件进行消息发布与订阅【 基于EMQX Cloud】

MQTT.fx软件使用简单介绍 MQTT.fx 的软件界面如下图所示&#xff0c;最上方为 MQTT Broker 连接地址栏&#xff0c;及其连接配置。其下方功能 Tabs 含有 Publish 发布栏、Subscribe 订阅栏、Scripts 脚本栏、Broker Status 状态消息栏、Log 日志信息控制栏。 连接之前要明确几…

BeautifulSoup4通过lxml使用Xpath,以及获取(定位)元素和其文本或者属性

环境&#xff1a;win10&#xff0c;python3.8.10 首先需要安装&#xff1a;beautifulsoup4&#xff0c;lxml 使用命令&#xff1a; pip38 install beautifulsoup4 pip38 install lxml 安装完毕后查看一下&#xff1a; 写代码&#xff1a; from bs4 import BeautifulSoup …

el-transfer和el-tree进行结合搞一个树形穿梭框

由于业务需求需要在穿梭框里使用树形结构&#xff0c;但是本身element里并不支持&#xff0c;于是参考了别的大佬发的文章作为思路及后续自己新增了一些处理功能。 目录 1.拷贝代码放到自己的项目目录中 2.改造el-transfer的源码 3.修改tree-transfer-panel.vue文件 4.修改…

Excel透视表:快速计算数据分析指标的利器

文章目录 概述1.数据透视表基本操作1.1准备数据&#xff1a;1.2创建透视表&#xff1a;1.3设置透视表字段&#xff1a;1.4多级分类汇总和交叉汇总的差别1.5计算汇总数据&#xff1a;1.6透视表美化&#xff1a;1.7筛选和排序&#xff1a;1.8更新透视表&#xff1a; 2.数据透视-数…

Could not create connection to database server的错误原因

1、使用MyBatis 连接数据库报错 org.apache.ibatis.exceptions.PersistenceException: ### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. ### The error may …

Docker(四)容器相关操作及问题处理

目录 一、进入、退出容器操作 二、查看Docker 容器的配置文件 方法一&#xff1a;进入docker容器内进行查看 方法二&#xff1a;通过数据卷挂载方式查看配置文件 方法三&#xff1a;使用Docker可视化工具查看配置文件 三、容器与宿主机时间同步 方法一&#xff1a;创建启…

java抽象类,接口,枚举练习题

第一题&#xff1a; 答案&#xff1a; class Animal{//成员变量protected String name;protected int weight;//构造方法public Animal(){this.name"refer";this.weight50;}public Animal(String name,int weight){this.namename;this.weightweight;}//成员方法publ…

R可视化:可发表的Y轴截断图

Y轴截断图by ggprism Y轴截断图by ggprism 介绍 ggplot2绘制Y轴截断图by ggprism加载R包 knitr::opts_chunk$set(message = FALSE, warning = FALSE)library(tidyverse) library(ggprism) library(patchwork)rm(list = ls()) options(stringsAsFactors = F) options(future.…

回溯大法总结

前言 本篇博客将分两步来进行&#xff0c;首先谈谈我对回溯法的理解&#xff0c;然后通过若干道题来进行讲解&#xff0c;最后总结 对回溯法的理解 回溯法可以看做蛮力法的升级版&#xff0c;它在解决问题时的每一步都尝试所有可能的选项&#xff0c;最终找出所以可行的方案…

redis中String,Hash类型用法与场景使用

String 用法 1. 设置键值对 &#xff08;1&#xff09;设置键值对使用 set 命令设置 key 的值。 返回值&#xff1a;ok&#xff0c;如果 key 已经存在&#xff0c;set 命令会覆盖旧值。 &#xff08;2&#xff09;使用 setex 命令设置 key 的值并为其设置过期时间&#xff…

短剧APP开发,短剧行业发展下的财富密码

今年以来&#xff0c;短剧市场展现出了繁荣发展的态势&#xff0c;成为了一个风口赛道。 短剧具有不拖沓、时长短、剧情紧凑等优势&#xff0c;顺应了当代人的生活&#xff0c;是当代人的“电子榨菜”。 短剧的快速发展同时也带动了新业态新模式的发展&#xff0c;短剧APP就是…

鸿蒙OS开发:【一次开发,多端部署】(一多天气)项目

一多天气 介绍 本示例展示一个天气应用界面&#xff0c;包括首页、城市管理、添加城市、更新时间弹窗&#xff0c;体现一次开发&#xff0c;多端部署的能力。 1.本示例参考一次开发&#xff0c;多端部署的指导&#xff0c;主要使用响应式布局的栅格断点系统实现在不同尺寸窗…

“等保测评与安全运维的协同:保障企业网络安宁

"等保测评与安全运维的协同&#xff1a;保障企业网络安宁"是一个涉及信息安全领域的重要话题。这里&#xff0c;我们可以从几个方面来探讨这个主题。 1. 等保测评&#xff08;等级保护测评&#xff09; 等保测评&#xff0c;即信息安全等级保护测评&#xff0c;是依…

WordPress 发布了独立的 SQLite 插件

之前 WordPress 在官方的 Performance Lab 插件实现 SQLite 模块&#xff0c;现在重构 SQLite 的实现&#xff0c;并且将其发布成一个独立的插件&#xff1a;SQLite Database Integration。 独立 SQLite 插件 最初的功能模块实现是基于 aaemnnosttv 的 wp-sqlite-db 插件修改实…