[Pdbg] [PATCH 1/4] libpdbg: Validate hardware units at build time

Cyril Bur cyrilbur at gmail.com
Wed Mar 7 16:35:24 AEDT 2018


I'll send this to the list otherwise I'll forget.

Al and I decided to send our Core HTM patches and get them merged
first, I'll rebase this series onto those.

I don't expect any other changes in v2 unless someone wants to jump in.


On Tue, 2018-02-27 at 19:23 +1100, Cyril Bur wrote:
> Hardware unit structs such as struct htm contain a struct pdbg_target
> which can be passed around to create an abstraction. Currently there is
> a bit of extra runtime code used to guard against developers not
> declaring the struct pdbg_target member as the first member. If we can
> enforce this at build time then a some runtime can be removed.
> 
> This patch enforces that the struct pdbg_target member of hardware
> units is always the first member at build time.
> 
> The only caveat is that compiling with -O0 will result in a false
> negative - the build succeeding when it should not. We should be using
> litterally any other optimisation level so that isn't really a problem.
> 
> Signed-off-by: Cyril Bur <cyrilbur at gmail.com>
> ---
>  Makefile.am      |  2 +-
>  libpdbg/target.c | 10 ++++------
>  libpdbg/target.h | 16 ++++++++++++----
>  3 files changed, 17 insertions(+), 11 deletions(-)
> 
> diff --git a/Makefile.am b/Makefile.am
> index 4156b21..099a035 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -8,7 +8,7 @@ include libfdt/Makefile.libfdt
>  bin_PROGRAMS = pdbg
>  
>  ACLOCAL_AMFLAGS = -Im4
> -AM_CFLAGS = -I$(top_srcdir)/ccan/array_size -Wall -Werror
> +AM_CFLAGS = -I$(top_srcdir)/ccan/array_size -Wall -Werror -O2
>  
>  pdbg_SOURCES = \
>  	src/main.c src/cfam.c src/scom.c src/reg.c src/mem.c src/thread.c \
> diff --git a/libpdbg/target.c b/libpdbg/target.c
> index 1eb85bb..07159d2 100644
> --- a/libpdbg/target.c
> +++ b/libpdbg/target.c
> @@ -254,7 +254,7 @@ struct hw_unit_info *find_compatible_target(const char *compat)
>  	struct pdbg_target *target;
>  
>  	for (p = &__start_hw_units; p < (struct hw_unit_info **) &__stop_hw_units; p++) {
> -		target = (*p)->hw_unit + (*p)->struct_target_offset;
> +		target = (*p)->hw_unit;
>  		if (!strcmp(target->compatible, compat))
>  			return *p;
>  	}
> @@ -268,7 +268,6 @@ void pdbg_targets_init(void *fdt)
>  	const struct dt_property *p;
>  	struct pdbg_target_class *target_class;
>  	struct hw_unit_info *hw_unit_info;
> -	void *new_hw_unit;
>  	struct pdbg_target *new_target;
>  	uint32_t index;
>  
> @@ -283,10 +282,9 @@ void pdbg_targets_init(void *fdt)
>  		hw_unit_info = find_compatible_target(p->prop);
>  		if (hw_unit_info) {
>  			/* We need to allocate a new target */
> -			new_hw_unit = malloc(hw_unit_info->size);
> -			assert(new_hw_unit);
> -			memcpy(new_hw_unit, hw_unit_info->hw_unit, hw_unit_info->size);
> -			new_target = new_hw_unit + hw_unit_info->struct_target_offset;
> +			new_target = malloc(hw_unit_info->size);
> +			assert(new_target);
> +			memcpy(new_target, hw_unit_info->hw_unit, hw_unit_info->size);
>  			new_target->dn = dn;
>  			dn->target = new_target;
>  			index = dt_prop_get_u32_def(dn, "index", -1);
> diff --git a/libpdbg/target.h b/libpdbg/target.h
> index 0a618e2..2bc7dba 100644
> --- a/libpdbg/target.h
> +++ b/libpdbg/target.h
> @@ -18,6 +18,7 @@
>  
>  #include <stdint.h>
>  #include <ccan/list/list.h>
> +#include <ccan/str/str.h>
>  #include <ccan/container_of/container_of.h>
>  #include "compiler.h"
>  #include "device.h"
> @@ -60,16 +61,23 @@ extern struct list_head empty_list;
>  struct hw_unit_info {
>  	void *hw_unit;
>  	size_t size;
> -	size_t struct_target_offset;
>  };
>  
>  /* We can't pack the structs themselves directly into a special
>   * section because there doesn't seem to be any standard way of doing
>   * that due to alignment rules. So instead we pack pointers into a
> - * special section. */
> + * special section.
> + *
> + * If this macro fails to compile for you, you've probably not
> + * declared the struct pdbg_target as the first member of the
> + * container struct. Not doing so will break other assumptions.
> + * */
>  #define DECLARE_HW_UNIT(name)						\
> -	const struct hw_unit_info __used name ##_hw_unit = \
> -	{ .hw_unit = &name, .size = sizeof(name), .struct_target_offset = container_off(typeof(name), target) }; \
> +	static inline void name ##_hw_unit_check(void) {		\
> +		((void)sizeof(char[1 - 2 * (container_off(typeof(name), target) != 0)])); \
> +	}								\
> +	const struct hw_unit_info __used name ##_hw_unit =              \
> +	{ .hw_unit = &name, .size = sizeof(name) }; 	                \
>  	const struct hw_unit_info __used __section("hw_units") *name ##_hw_unit_p = &name ##_hw_unit
>  
>  struct htm {
> -- 
> 2.16.2
> 


More information about the Pdbg mailing list