• imx6ul链接地址、运行地址、加载地址、位置无关、mmu的关系


    0 说明

            本文主要说明在裸机和linux启动中链接地址和运行地址的关系,但是这俩哥们的关系和位置无关码以及MMU有所牵扯,所以放到一起进行说明。

            以下针对imx6ull处理器平台

    1、imx6u的Memory Maps

            首先确定一下物理内存的开始地址,不同处理器DDR或者RAM的基地值是不一样的。这个需要根据平台的参考手册查找,对于imx6ul,在数据手册Memory Maps一章,有如下图:

            也就是说,CPU中的0x8000000地址对应物理内存的起始位置。而并不简单的是0地址对应物理内存的0地址。

            因此我们写一个裸机程序的时候,指定运行地址的时候,一般是0x80008000(uboot),这里0x80008000指的是处理器中的地址,对应到DDR,也就是偏移为0x8000位置处。

    2、链接地址

            这个地址是在程序构建到链接阶段的时候确定下来的。

    2.1 链接地址的两种设置方式

    •  -Ttext 0x80002000
    • 链接脚本

    2.2 链接后的影响

            链接后,查看反汇编可以参考,代码段开始时候的地址正是指定的链接地址。

     3、运行地址

            运行地址是和pc指针(r15寄存器)有关的地址。

    举例1:uboot加载裸机并跳转执行

            uboot中通过tftp将程序加载到内存0x80002000处,然后通过go 0x80002000,开始执行。这个时候0x80002000就是运行地址。

    1. => tftp 0x80002000 boot.bin;go 0x80002000
    2. TFTP from server 192.168.1.108; our IP address is 192.168.1.187
    3. Filename 'boot.bin'.
    4. Load address: 0x80002000
    5. Loading: #################################################################
    6. ######
    7. 2 MiB/s
    8. done
    9. Bytes transferred = 1040520 (fe088 hex)
    10. ## Starting application at 0x80002000 ...
    11. ****************************************************
    12. ************* IMX6UL Bootloader RUN ****************
    13. ****************************************************
    14. 1.Init io/clock/uart/usdhc/irq... success
    15. 2.Start Copy kerner and dtb to ddr
    16. 2.1 Mount fatfs [ SUCCESS ]
    17. 2.3 Open zImage file [ SUCCESS ]
    18. 2.4 Open dtb file [ SUCCESS ]
    19. 2.5 Read kernel file to ENTRY ADDR:0x80800000[ SUCCESS ]
    20. 2.6 Read dtb file to 0x83000000[ SUCCESS ]
    21. 3.Starting kernel ...
    22. Booting Linux on physical CPU 0x0
    23. Linux version 4.1.15-g696dd24-dirty (root@xxzh) (gcc version 6.2.1 20161016 (Linaro GCC 6.2-2016.11) ) #68 SMP PREEMPT Thu Aug 11 09:45:05 CST 2022
    24. CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=10c53c7d
    25. CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
    26. Machine model: Freescale i.MX6 ULL 14x14 EVK Board
    27. Reserved memory: created CMA memory pool at 0x8c000000, size 320 MiB
    28. Reserved memory: initialized node linux,cma, compatible id shared-dma-pool
    29. Memory policy: Data cache writealloc
    30. PERCPU: Embedded 12 pages/cpu @8bb33000 s16908 r8192 d24052 u49152
    31. Built 1 zonelists in Zone order, mobility grouping on. Total pages: 130048
    32. Kernel command line: console=ttymxc3,115200 imx2-wdt.timeout=120 root=/dev/mmcblk1p2 rootwait rw
    33. PID hash table entries: 2048 (order: 1, 8192 bytes)
    34. Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
    35. Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
    36. Memory: 180876K/524288K available (6847K kernel code, 377K rwdata, 2316K rodata, 400K init, 422K bss, 15732K reserved, 327680K cma-reserved, 0K highmem)
    37. Virtual kernel memory layout:
    38. vector : 0xffff0000 - 0xffff1000 ( 4 kB)
    39. fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
    40. vmalloc : 0xa0800000 - 0xff000000 (1512 MB)
    41. lowmem : 0x80000000 - 0xa0000000 ( 512 MB)
    42. pkmap : 0x7fe00000 - 0x80000000 ( 2 MB)
    43. modules : 0x7f000000 - 0x7fe00000 ( 14 MB)
    44. .text : 0x80008000 - 0x808fb110 (9165 kB)
    45. .init : 0x808fc000 - 0x80960000 ( 400 kB)
    46. .data : 0x80960000 - 0x809be598 ( 378 kB)
    47. .bss : 0x809c1000 - 0x80a2a948 ( 423 kB)

     举例2:mkimage指定可执行程序开始运行的地址

            imx6ul在裸机编译产生bin文件后,可以通过如下命令产生imx文件,增加一个头部,bootrom会根据头部中的信息,把可执行程序放到0x80002000,在这个地址开始运行,这个地址就是运行地址。

    ./tools/mkimage -n ./tools/imximage.cfg.cfgtmp -T imximage -e 0x80002000 -d $(TARGET).bin $(TARGET).imx

    链接地址和运行地址的区别

    链接地址=运行地址

           程序中有函数调用,有全局变量,指定链接地址后,每一个数据都被安排好地址了。程序运行的时候, 可以找到对应的资源,上面的例子中,程序的链接地址和运行地址一样,所以运行不会有问题。

    链接地址≠运行地址

            链接指定了0x80002000地址,但是uboot中不是go 0x80002000,那么可以运行吗,也许可以,需要看程序是不是位置无关码,如果是那么就可以正常运行,因为位置无关码下,链接地址将不会有影响。

            但是一个程序完全实现位置无关太难了,但是这俩地址又无法做到相同,那怎么办呢,那就是重定位,程序开始的时候运行位置无关码,通过前期位置无关码,把程序拷贝到链接地址处开始运行。

    位置无关码

            这里不做太多说明,代码执行的时候使用相对地址调转,所以链接地址不会影响。

    重定位

            链接地址≠运行地址的时候,可以通过重定位,在代码开始使用位置无关码将程序拷贝到正确的链接地址去,所以重定位用在链接地址≠运行地址的场景下。

    MMU对链接、运行地址的影响

            这里主要是在linux引导时候会产生的情况。对于arm32平台,用户空间一般是3G/1G内核空间。因此内核的链接地址一般是0xc0008000。也就大于了0xc0000000。

            但是程序加载ddr的时候并不一定会被加载到0xc0008000,正如开始的时候说的imx6ul是从0x80000000开始,如果ddr只有512M,那么不可能把内核直接放到0xc0008000处。

            不过,对于imx6ul的内核空间一般是2G,也就可以以0x80008000作为链接地址,可以使得运行地址和链接地址一致。

            对于别的平台,可以在开启MMU之前,临时页表创建的时候,将内核链接地址和实际的物理地址映射起来。

            开启MMU前,位置无关码,链接地址≠运行地址,开启后链接地址=运行地址。

  • 相关阅读:
    redis 缓存jwt令牌设置更新时间 BUG修复
    基于PHP+MySQL高校毕业设计管理系统的设计与实现
    java技术:nacos
    axios.defaults.baseURL的三种配置方法
    [glacierctf 2022] 只会3个
    JAVA反编译工具:JADX-GUI、
    C++第十单元 查找与检索10.1 顺序查找10.2 二分查找
    iOS - 多线程-GCD
    tcp/ip该来的还是得来
    docker实战学习2022版本(八)之compose容器编排和轻量级可视化工具Portainer
  • 原文地址:https://blog.csdn.net/fengyuwuzu0519/article/details/126426068