开发环境的搭建涉及友善smart-210开发板作为平台。在进行so动态库文件头分析时,需明确其本质为ELF文件,且利用Elf32_Ehdr结构体定义ELF32头文件。将armeabi-v7a类型的so动态库文件放置于Linux系统路径中,然后在Linux终端进入文件目录,执行"readelf -h xxxx.so"命令,以查看文件头部信息。
文件头部信息包括Magic/e_ident[]用于标识ELF目标文件,Class标记文件类型为32位ELF格式,Data指示数据组织格式为小端格式,Version为当前文件头版本号1。OS/ABI描述操作系统类,ABI Version为ABI版本号0。Type/e_type指明文件类型,这里是共享库(Shared Library)。Machine/e_machine显示机器平台类型为ARM类型,Version/e_version为当前目标文件版本号0x01。Entry point address/e_entry表示程序入口地址,Stars of program headers/e_phoff记录程序头表文件偏移,Stars of section headers/e_shoff记录节区头文件偏移。Flasgs/e_flags为处理器相关标识,Size of this header/e_ehsize表示ELF头文件大小,Size of program headers/e_phentsize表示程序头表头目大小。Number of program headers/e_phnum表示程序头表条目数量,Size of section headers/shentsize表示节区头表条目大小,Number of section headers/e_shnum为节区头表条目数量。节区头字符表索引/e_shstrndx。
程序头表通过Elf32_Phdr结构体描述,此表为数组,数组元素存储程序头表条目,描述段或其它信息以准备程序运行。文件段包含多个节区,程序头表仅在可执行文件或共享对象文件中有意义。
反编译so动态库方法采用IDA软件。首先解压安装包,安装时注意避免中文路径,随后根据ReadMe文档获取密钥。安装完成后,打开软件并点击“GO”按钮,拖拽so动态库文件至工作区,点击“OK”按钮等待反编译完成。反编译后,工作区显示包含机器码的Hex View-1窗口、汇编代码的IDA View-A窗口以及保存函数名的Function window窗口。通过双击函数名定位到对应函数的汇编代码。使用Ctrl+F搜索特定函数名,双击函数名查看汇编代码,按下F5即可转换为C代码。
❷ 怎么修改android 启动过程中的第二个开机画面
第一个开机画面是在内核启动的过程中出现的,它是一个静态的画面。第二个开机画面是在init进程启动的过程中出现的,它也是一个静态的画面。第三个开机画面是在系统服务启动的过程中出现的,它是一个动态的画面。无论是哪一个画面,它们都是在一个称为帧缓冲区(frame buffer,简称fb)的硬件设备上进行渲染的。接下来,我们就分别分析这三个画面是如何在fb上显示的。
1. 第一个开机画面的显示过程
Android系统的第一个开机画面其实是Linux内核的启动画面。在默认情况下,这个画面是不会出现的,除非我们在编译内核的时候,启用以下两个编译选项:
CONFIG_FRAMEBUFFER_CONSOLE
CONFIG_LOGO
第一个编译选项表示内核支持帧缓冲区控制台,它对应的配置菜单项为:Device Drivers ---> Graphics support ---> Console display driver support ---> Framebuffer Console support。第二个编译选项表示内核在启动的过程中,需要显示LOGO,它对应的配置菜单项为:Device Drivers ---> Graphics support ---> Bootup logo。配置Android内核编译选项可以参考在Ubuntu上下载、编译和安装Android最新内核源代码(Linux Kernel)一文。
帧缓冲区硬件设备在内核中有一个对应的驱动程序模块fbmem,它实现在文件kernel/goldfish/drivers/video/fbmem.c中,它的初始化函数如下所示:
/**
* fbmem_init - init frame buffer subsystem
*
* Initialize the frame buffer subsystem.
*
* NOTE: This function is _only_ to be called by drivers/char/mem.c.
*
*/
static int __init
fbmem_init(void)
{
proc_create("fb", 0, NULL, &fb_proc_fops);
if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
printk("unable to get major %d for fb devs\n", FB_MAJOR);
fb_class = class_create(THIS_MODULE, "graphics");
if (IS_ERR(fb_class)) {
printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
fb_class = NULL;
}
return 0;
}
这个函数首先调用函数proc_create在/proc目录下创建了一个fb文件,接着又调用函数register_chrdev来注册了一个名称为fb的字符设备,最后调用函数class_create在/sys/class目录下创建了一个graphics目录,用来描述内核的图形系统。
模块fbmem除了会执行上述初始化工作之外,还会导出一个函数register_framebuffer:
EXPORT_SYMBOL(register_framebuffer);
这个函数在内核的启动过程会被调用,以便用来执行注册帧缓冲区硬件设备的操作,它的实现如下所示:
/**
* register_framebuffer - registers a frame buffer device
* @fb_info: frame buffer info structure
*
* Registers a frame buffer device @fb_info.
*
* Returns negative errno on error, or zero for success.
*
*/
int
register_framebuffer(struct fb_info *fb_info)
{
int i;
struct fb_event event;
......
if (num_registered_fb == FB_MAX)
return -ENXIO;
......
num_registered_fb++;
for (i = 0 ; i < FB_MAX; i++)
if (!registered_fb[i])
break;
fb_info->node = i;
mutex_init(&fb_info->lock);
fb_info->dev = device_create(fb_class, fb_info->device,
MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
if (IS_ERR(fb_info->dev)) {
/* Not fatal */
printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
fb_info->dev = NULL;
} else
fb_init_device(fb_info);
......
registered_fb[i] = fb_info;
event.info = fb_info;
fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
return 0;
}
由于系统中可能会存在多个帧缓冲区硬件设备,因此,fbmem模块使用一个数组registered_fb保存所有已经注册了的帧缓冲区硬件设备,其中,每一个帧缓冲区硬件都是使用一个结构体fb_info来描述的。