linker list

2024-02-06 14:04
文章标签 list linker

本文主要是介绍linker list,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

linker list是利用lds 描述符实现同类型数据连续排布的一种机制。
下面是uboot里面的应用说明

lds文件里面需要增加section描述:

. = ALIGN(4);.u_boot_list : {KEEP(*(SORT(.u_boot_list*)));}

linker_list.h:

/* SPDX-License-Identifier: GPL-2.0+ */
/** include/linker_lists.h** Implementation of linker-generated arrays** Copyright (C) 2012 Marek Vasut <marex@denx.de>*/#ifndef __LINKER_LISTS_H__
#define __LINKER_LISTS_H__#include <linux/compiler.h>/** There is no use in including this from ASM files.* So just don't define anything when included from ASM.*/#if !defined(__ASSEMBLY__)/*** llsym() - Access a linker-generated array entry* @_type:	Data type of the entry* @_name:	Name of the entry* @_list:	name of the list. Should contain only characters allowed*		in a C variable name!*/
#define llsym(_type, _name, _list) \((_type *)&_u_boot_list_2_##_list##_2_##_name)/*** ll_entry_declare() - Declare linker-generated array entry* @_type:	Data type of the entry* @_name:	Name of the entry* @_list:	name of the list. Should contain only characters allowed*		in a C variable name!** This macro declares a variable that is placed into a linker-generated* array. This is a basic building block for more advanced use of linker-* generated arrays. The user is expected to build their own macro wrapper* around this one.** A variable declared using this macro must be compile-time initialized.** Special precaution must be made when using this macro:** 1) The _type must not contain the "static" keyword, otherwise the*    entry is generated and can be iterated but is listed in the map*    file and cannot be retrieved by name.** 2) In case a section is declared that contains some array elements AND*    a subsection of this section is declared and contains some elements,*    it is imperative that the elements are of the same type.** 3) In case an outer section is declared that contains some array elements*    AND an inner subsection of this section is declared and contains some*    elements, then when traversing the outer section, even the elements of*    the inner sections are present in the array.** Example:** ::**   ll_entry_declare(struct my_sub_cmd, my_sub_cmd, cmd_sub) = {*           .x = 3,*           .y = 4,*   };*/
#define ll_entry_declare(_type, _name, _list)				\_type _u_boot_list_2_##_list##_2_##_name __aligned(4)		\__attribute__((unused,				\section(".u_boot_list_2_"#_list"_2_"#_name)))/*** ll_entry_declare_list() - Declare a list of link-generated array entries* @_type:	Data type of each entry* @_name:	Name of the entry* @_list:	name of the list. Should contain only characters allowed*		in a C variable name!** This is like ll_entry_declare() but creates multiple entries. It should* be assigned to an array.** ::**   ll_entry_declare_list(struct my_sub_cmd, my_sub_cmd, cmd_sub) = {*        { .x = 3, .y = 4 },*        { .x = 8, .y = 2 },*        { .x = 1, .y = 7 }*   };*/
#define ll_entry_declare_list(_type, _name, _list)			\_type _u_boot_list_2_##_list##_2_##_name[] __aligned(4)		\__attribute__((unused,				\section(".u_boot_list_2_"#_list"_2_"#_name)))/** We need a 0-byte-size type for iterator symbols, and the compiler* does not allow defining objects of C type 'void'. Using an empty* struct is allowed by the compiler, but causes gcc versions 4.4 and* below to complain about aliasing. Therefore we use the next best* thing: zero-sized arrays, which are both 0-byte-size and exempt from* aliasing warnings.*//*** ll_entry_start() - Point to first entry of linker-generated array* @_type:	Data type of the entry* @_list:	Name of the list in which this entry is placed** This function returns ``(_type *)`` pointer to the very first entry of a* linker-generated array placed into subsection of .u_boot_list section* specified by _list argument.** Since this macro defines an array start symbol, its leftmost index* must be 2 and its rightmost index must be 1.** Example:** ::**   struct my_sub_cmd *msc = ll_entry_start(struct my_sub_cmd, cmd_sub);*/
#define ll_entry_start(_type, _list)					\
({									\static char start[0] __aligned(4) __attribute__((unused,	\section(".u_boot_list_2_"#_list"_1")));			\(_type *)&start;						\
})/*** ll_entry_end() - Point after last entry of linker-generated array* @_type:	Data type of the entry* @_list:	Name of the list in which this entry is placed*		(with underscores instead of dots)** This function returns ``(_type *)`` pointer after the very last entry of* a linker-generated array placed into subsection of .u_boot_list* section specified by _list argument.** Since this macro defines an array end symbol, its leftmost index* must be 2 and its rightmost index must be 3.** Example:** ::**   struct my_sub_cmd *msc = ll_entry_end(struct my_sub_cmd, cmd_sub);*/
#define ll_entry_end(_type, _list)					\
({									\static char end[0] __aligned(4) __attribute__((unused,		\section(".u_boot_list_2_"#_list"_3")));			\(_type *)&end;							\
})
/*** ll_entry_count() - Return the number of elements in linker-generated array* @_type:	Data type of the entry* @_list:	Name of the list of which the number of elements is computed** This function returns the number of elements of a linker-generated array* placed into subsection of .u_boot_list section specified by _list* argument. The result is of an unsigned int type.** Example:** ::**   int i;*   const unsigned int count = ll_entry_count(struct my_sub_cmd, cmd_sub);*   struct my_sub_cmd *msc = ll_entry_start(struct my_sub_cmd, cmd_sub);*   for (i = 0; i < count; i++, msc++)*           printf("Entry %i, x=%i y=%i\n", i, msc->x, msc->y);*/
#define ll_entry_count(_type, _list)					\({								\_type *start = ll_entry_start(_type, _list);		\_type *end = ll_entry_end(_type, _list);		\unsigned int _ll_result = end - start;			\_ll_result;						\})/*** ll_entry_get() - Retrieve entry from linker-generated array by name* @_type:	Data type of the entry* @_name:	Name of the entry* @_list:	Name of the list in which this entry is placed** This function returns a pointer to a particular entry in linker-generated* array identified by the subsection of u_boot_list where the entry resides* and it's name.** Example:** ::**   ll_entry_declare(struct my_sub_cmd, my_sub_cmd, cmd_sub) = {*           .x = 3,*           .y = 4,*   };*   ...*   struct my_sub_cmd *c = ll_entry_get(struct my_sub_cmd, my_sub_cmd, cmd_sub);*/
#define ll_entry_get(_type, _name, _list)				\({								\extern _type _u_boot_list_2_##_list##_2_##_name;	\_type *_ll_result =					\&_u_boot_list_2_##_list##_2_##_name;		\_ll_result;						\})/*** ll_start() - Point to first entry of first linker-generated array* @_type:	Data type of the entry** This function returns ``(_type *)`` pointer to the very first entry of* the very first linker-generated array.** Since this macro defines the start of the linker-generated arrays,* its leftmost index must be 1.** Example:** ::**   struct my_sub_cmd *msc = ll_start(struct my_sub_cmd);*/
#define ll_start(_type)							\
({									\static char start[0] __aligned(4) __attribute__((unused,	\section(".u_boot_list_1")));				\(_type *)&start;						\
})/*** ll_end() - Point after last entry of last linker-generated array* @_type:	Data type of the entry** This function returns ``(_type *)`` pointer after the very last entry of* the very last linker-generated array.** Since this macro defines the end of the linker-generated arrays,* its leftmost index must be 3.** Example:** ::**   struct my_sub_cmd *msc = ll_end(struct my_sub_cmd);*/
#define ll_end(_type)							\
({									\static char end[0] __aligned(4) __attribute__((unused,		\section(".u_boot_list_3")));				\(_type *)&end;							\
})#endif /* __ASSEMBLY__ */#endif	/* __LINKER_LISTS_H__ */

ll_entry_declare_list 和ll_entry_declare差别是前者是数组声明,一次可以声明多个条目,后者只声明(定义)一个条目。

ll_entry_start(_type, _list) 获取该类型列表首个条目地址

ll_entry_get(_type, _name, _list) 根据名字 返回条目地址

ll_entry_count(_type, _list) 返回该类型条目数

使用实例

参考driver的定义:

struct driver {char *name;enum uclass_id id;const struct udevice_id *of_match;int (*bind)(struct udevice *dev);int (*probe)(struct udevice *dev);int (*remove)(struct udevice *dev);int (*unbind)(struct udevice *dev);int (*ofdata_to_platdata)(struct udevice *dev);int (*child_post_bind)(struct udevice *dev);int (*child_pre_probe)(struct udevice *dev);int (*child_post_remove)(struct udevice *dev);int priv_auto_alloc_size;int platdata_auto_alloc_size;int per_child_auto_alloc_size;int per_child_platdata_auto_alloc_size;const void *ops;	/* driver-specific operations */uint32_t flags;
};/* Declare a new U-Boot driver */
#define U_BOOT_DRIVER(__name)						\ll_entry_declare(struct driver, __name, driver)

usb hub driver

U_BOOT_DRIVER(usb_generic_hub) = {
.name = “usb_hub”,
.id = UCLASS_USB_HUB,
.of_match = usb_hub_ids,
.flags = DM_FLAG_ALLOC_PRIV_DMA,
};

这篇关于linker list的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/684549

相关文章

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

Collection List Set Map的区别和联系

Collection List Set Map的区别和联系 这些都代表了Java中的集合,这里主要从其元素是否有序,是否可重复来进行区别记忆,以便恰当地使用,当然还存在同步方面的差异,见上一篇相关文章。 有序否 允许元素重复否 Collection 否 是 List 是 是 Set AbstractSet 否

【Python报错已解决】AttributeError: ‘list‘ object has no attribute ‘text‘

🎬 鸽芷咕:个人主页  🔥 个人专栏: 《C++干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 文章目录 前言一、问题描述1.1 报错示例1.2 报错分析1.3 解决思路 二、解决方法2.1 方法一:检查属性名2.2 步骤二:访问列表元素的属性 三、其他解决方法四、总结 前言 在Python编程中,属性错误(At

List list = new ArrayList();和ArrayList list=new ArrayList();的区别?

List是一个接口,而ArrayList 是一个类。 ArrayList 继承并实现了List。 List list = new ArrayList();这句创建了一个ArrayList的对象后把上溯到了List。此时它是一个List对象了,有些ArrayList有但是List没有的属性和方法,它就不能再用了。而ArrayList list=new ArrayList();创建一对象则保留了A

处理List采用并行流处理时,通过ForkJoinPool来控制并行度失控的问题

在使用parallelStream进行处理list时,如不指定线程池,默认的并行度采用cpu核数进行并行,这里采用ForJoinPool来控制,但循环中使用了redis获取key时,出现失控。具体上代码。 @RunWith(SpringRunner.class)@SpringBootTest(classes = Application.class)@Slf4jpublic class Fo

Java中集合类Set、List和Map的区别

Java中的集合包括三大类,它们是Set、List和Map,它们都处于java.util包中,Set、List和Map都是接口,它们有各自的实现类。Set的实现类主要有HashSet和TreeSet,List的实现类主要有ArrayList,Map的实现类主要有HashMap和TreeMap。那么它们有什么区别呢? Set中的对象不按特定方式排序,并且没有重复对象。但它的有些实现类能对集合中的对

List对象过滤

List materialInventoryList = materialInventories.stream().filter(mat -> mat.getQty().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList()); stream().filter()方法可以过滤掉List的数据

c++stack和list 介绍

stack介绍 堆栈是一种容器适配器,专门设计用于在 LIFO 上下文(后进先出)中运行,其中元素仅从容器的一端插入和提取。 堆栈作为容器适配器实现,容器适配器是使用特定容器类的封装对象作为其基础容器 的类,提供一组特定的成员函数来访问其元素。元素从特定容器的 “back” 推送或弹出,这称为堆栈的顶部。 stack接口 stack() 构造空的栈 empty() 检测stack是否为

C++——list的实现

目录 0.前言 1.节点类  2.迭代器类  ①普通迭代器 ②const迭代器  ③模板迭代器 3.list类  3.1 clear、析构函数、swap ①clear ② 析构函数  ③ swap 3.2构造函数  ①无参构造  ②赋值构造 3.3 迭代器 3.4插入函数 ①insert插入 ②头插 ③尾插 3.5 删除函数 ①erase删除 ②头删

Python中如何实现列表推导式(List Comprehension)

Python中的列表推导式(List Comprehension)是一种简洁且高效的方式来创建列表。它不仅让代码更加简洁,而且通常比使用循环和条件语句生成列表更快。列表推导式的基本形式允许你从现有的列表或其他可迭代对象中创建新的列表,同时应用过滤和转换操作。下面我将详细解释列表推导式的概念、基本语法、高级用法以及其在实际应用中的优势。 一、列表推导式的基本概念 列表推导式是Python中的一种