[v2,3/3] trace: fix undefined behavior in register

Message ID 20250130145849.82003-3-david.marchand@redhat.com (mailing list archive)
State Superseded
Delegated to: Thomas Monjalon
Headers
Series [v2,1/3] trace: support expression for blob length |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation success Compilation OK
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS
ci/intel-Testing success Testing PASS
ci/github-robot: build success github build: passed
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-marvell-Functional success Functional Testing PASS
ci/intel-Functional success Functional PASS
ci/iol-abi-testing success Testing PASS
ci/iol-unit-amd64-testing success Testing PASS
ci/iol-sample-apps-testing success Testing PASS
ci/iol-unit-arm64-testing success Testing PASS
ci/iol-compile-arm64-testing success Testing PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-compile-amd64-testing success Testing PASS
ci/iol-broadcom-Performance success Performance Testing PASS

Commit Message

David Marchand Jan. 30, 2025, 2:58 p.m. UTC
Registering a tracepoint handler was resulting so far in undefined
behavior at runtime.

The RTE_TRACE_POINT_REGISTER() macro was casting the tracepoint handler
(which expects arguments) to a void (*)(void).
At runtime, calling this handler while registering resulted in
reading the current stack with no relation to this function prototype.

Instead, declare an additional inline _register() handler for each
tracepoint and make sure that the emitting macros in
rte_trace_point_register.h only work on arguments name and type.

The original tracepoint handler prototype is adjusted by adding a
__rte_unused for each argument (since emitting macros do nothing
with them).
This last part introduces an implementation limit of 15 arguments.

With this change in place, the workaround in dmadev tracepoints can be
removed.

Signed-off-by: David Marchand <david.marchand@redhat.com>
---
 lib/dmadev/rte_dmadev_trace.h              | 12 -------
 lib/dmadev/rte_dmadev_trace_fp.h           | 14 --------
 lib/eal/include/rte_trace_point.h          |  4 +++
 lib/eal/include/rte_trace_point_register.h | 42 +++++++++++++++++++---
 4 files changed, 42 insertions(+), 30 deletions(-)
  

Comments

Stephen Hemminger Jan. 30, 2025, 7:10 p.m. UTC | #1
On Thu, 30 Jan 2025 15:58:49 +0100
David Marchand <david.marchand@redhat.com> wrote:

> Registering a tracepoint handler was resulting so far in undefined
> behavior at runtime.
> 
> The RTE_TRACE_POINT_REGISTER() macro was casting the tracepoint handler
> (which expects arguments) to a void (*)(void).
> At runtime, calling this handler while registering resulted in
> reading the current stack with no relation to this function prototype.
> 
> Instead, declare an additional inline _register() handler for each
> tracepoint and make sure that the emitting macros in
> rte_trace_point_register.h only work on arguments name and type.
> 
> The original tracepoint handler prototype is adjusted by adding a
> __rte_unused for each argument (since emitting macros do nothing
> with them).
> This last part introduces an implementation limit of 15 arguments.
> 
> With this change in place, the workaround in dmadev tracepoints can be
> removed.
> 
> Signed-off-by: David Marchand <david.marchand@redhat.com>

When I build with -Db_santize=undefined the following warning shows up.
It seems related.

In function ‘rte_ethdev_trace_get_dcb_info’,
    inlined from ‘rte_eth_dev_get_dcb_info’ at ../lib/ethdev/rte_ethdev.c:6720:2:
../lib/eal/include/rte_trace_point.h:381:9: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
  381 |         memcpy(mem, &(in), sizeof(in)); \
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../lib/eal/include/rte_trace_point.h:53:9: note: in definition of macro ‘__RTE_TRACE_POINT’
   53 |         __VA_ARGS__ \
      |         ^~~~~~~~~~~
../lib/ethdev/ethdev_trace.h:1213:1: note: in expansion of macro ‘RTE_TRACE_POINT’
 1213 | RTE_TRACE_POINT(
      | ^~~~~~~~~~~~~~~
../lib/eal/include/rte_trace_point.h:399:9: note: in expansion of macro ‘__rte_trace_point_emit’
  399 |         __rte_trace_point_emit(len, uint8_t); \
      |         ^~~~~~~~~~~~~~~~~~~~~~
../lib/ethdev/ethdev_trace.h:1223:9: note: in expansion of macro ‘rte_trace_point_emit_blob’
 1223 |         rte_trace_point_emit_blob(dcb_info->tc_bws, num_tcs);
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~
In function ‘rte_eth_dev_get_dcb_info’:
cc1: note: destination object is likely at address zero
In function ‘rte_ethdev_trace_get_dcb_info’,
    inlined from ‘rte_eth_dev_get_dcb_info’ at ../lib/ethdev/rte_ethdev.c:6720:2:
../lib/eal/include/rte_trace_point.h:401:9: warning: ‘memset’ offset [0, 55] is out of the bounds [0, 0] [-Warray-bounds=]
  401 |         memset(RTE_PTR_ADD(mem, len), 0, RTE_TRACE_BLOB_LEN_MAX - len); \
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../lib/eal/include/rte_trace_point.h:53:9: note: in definition of macro ‘__RTE_TRACE_POINT’
   53 |         __VA_ARGS__ \
      |         ^~~~~~~~~~~
../lib/ethdev/ethdev_trace.h:1213:1: note: in expansion of macro ‘RTE_TRACE_POINT’
 1213 | RTE_TRACE_POINT(
      | ^~~~~~~~~~~~~~~
../lib/ethdev/ethdev_trace.h:1222:9: note: in expansion of macro ‘rte_trace_point_emit_blob’
 1222 |         rte_trace_point_emit_blob(dcb_info->prio_tc, num_user_priorities);
  
David Marchand Jan. 30, 2025, 9:06 p.m. UTC | #2
On Thu, Jan 30, 2025 at 8:10 PM Stephen Hemminger
<stephen@networkplumber.org> wrote:
>
> On Thu, 30 Jan 2025 15:58:49 +0100
> David Marchand <david.marchand@redhat.com> wrote:
>
> > Registering a tracepoint handler was resulting so far in undefined
> > behavior at runtime.
> >
> > The RTE_TRACE_POINT_REGISTER() macro was casting the tracepoint handler
> > (which expects arguments) to a void (*)(void).
> > At runtime, calling this handler while registering resulted in
> > reading the current stack with no relation to this function prototype.
> >
> > Instead, declare an additional inline _register() handler for each
> > tracepoint and make sure that the emitting macros in
> > rte_trace_point_register.h only work on arguments name and type.
> >
> > The original tracepoint handler prototype is adjusted by adding a
> > __rte_unused for each argument (since emitting macros do nothing
> > with them).
> > This last part introduces an implementation limit of 15 arguments.
> >
> > With this change in place, the workaround in dmadev tracepoints can be
> > removed.
> >
> > Signed-off-by: David Marchand <david.marchand@redhat.com>
>
> When I build with -Db_santize=undefined the following warning shows up.
> It seems related.
>
> In function ‘rte_ethdev_trace_get_dcb_info’,
>     inlined from ‘rte_eth_dev_get_dcb_info’ at ../lib/ethdev/rte_ethdev.c:6720:2:
> ../lib/eal/include/rte_trace_point.h:381:9: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
>   381 |         memcpy(mem, &(in), sizeof(in)); \
>       |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ../lib/eal/include/rte_trace_point.h:53:9: note: in definition of macro ‘__RTE_TRACE_POINT’
>    53 |         __VA_ARGS__ \
>       |         ^~~~~~~~~~~
> ../lib/ethdev/ethdev_trace.h:1213:1: note: in expansion of macro ‘RTE_TRACE_POINT’
>  1213 | RTE_TRACE_POINT(
>       | ^~~~~~~~~~~~~~~
> ../lib/eal/include/rte_trace_point.h:399:9: note: in expansion of macro ‘__rte_trace_point_emit’
>   399 |         __rte_trace_point_emit(len, uint8_t); \
>       |         ^~~~~~~~~~~~~~~~~~~~~~
> ../lib/ethdev/ethdev_trace.h:1223:9: note: in expansion of macro ‘rte_trace_point_emit_blob’
>  1223 |         rte_trace_point_emit_blob(dcb_info->tc_bws, num_tcs);

This is something I saw with optimisations (like O2 or O3 iirc) too.

Compiling and running with optimisations made GHA vm go out of memory,
so I have been testing only with O0 when it comes to ubsan.

In any case, this series is fixing just one undefined behavior.
Fixing all build and runtime errors seen with ubsan requires more work.
  
David Marchand Feb. 7, 2025, 8:49 a.m. UTC | #3
Hello Jerin, Sunil,

On Thu, Jan 30, 2025 at 3:59 PM David Marchand
<david.marchand@redhat.com> wrote:
>
> Registering a tracepoint handler was resulting so far in undefined
> behavior at runtime.
>
> The RTE_TRACE_POINT_REGISTER() macro was casting the tracepoint handler
> (which expects arguments) to a void (*)(void).
> At runtime, calling this handler while registering resulted in
> reading the current stack with no relation to this function prototype.
>
> Instead, declare an additional inline _register() handler for each
> tracepoint and make sure that the emitting macros in
> rte_trace_point_register.h only work on arguments name and type.
>
> The original tracepoint handler prototype is adjusted by adding a
> __rte_unused for each argument (since emitting macros do nothing
> with them).
> This last part introduces an implementation limit of 15 arguments.
>
> With this change in place, the workaround in dmadev tracepoints can be
> removed.
>
> Signed-off-by: David Marchand <david.marchand@redhat.com>

Can I have your opinion and review on this patch?

Thanks.
  
Sunil Kumar Kori Feb. 7, 2025, 11:39 a.m. UTC | #4
Hi David,

I will look into this at earliest and provide feedback.

Thanks

From: David Marchand <david.marchand@redhat.com>
Sent: Friday, February 7, 2025 2:20 PM
To: Jerin Jacob <jerinj@marvell.com>; Sunil Kumar Kori <skori@marvell.com>
Cc: dev@dpdk.org; Chengwen Feng <fengchengwen@huawei.com>; Kevin Laatz <kevin.laatz@intel.com>; Bruce Richardson <bruce.richardson@intel.com>; Tyler Retzlaff <roretzla@linux.microsoft.com>; Andre Muezerie <andremue@linux.microsoft.com>; Thomas Monjalon <thomas@monjalon.net>; Stephen Hemminger <stephen@networkplumber.org>
Subject: [EXTERNAL] Re: [PATCH v2 3/3] trace: fix undefined behavior in register

Hello Jerin, Sunil, On Thu, Jan 30, 2025 at 3: 59 PM David Marchand <david. marchand@ redhat. com> wrote: > > Registering a tracepoint handler was resulting so far in undefined > behavior at runtime. > > The RTE_TRACE_POINT_REGISTER()


Hello Jerin, Sunil,



On Thu, Jan 30, 2025 at 3:59 PM David Marchand

<david.marchand@redhat.com<mailto:david.marchand@redhat.com>> wrote:

>

> Registering a tracepoint handler was resulting so far in undefined

> behavior at runtime.

>

> The RTE_TRACE_POINT_REGISTER() macro was casting the tracepoint handler

> (which expects arguments) to a void (*)(void).

> At runtime, calling this handler while registering resulted in

> reading the current stack with no relation to this function prototype.

>

> Instead, declare an additional inline _register() handler for each

> tracepoint and make sure that the emitting macros in

> rte_trace_point_register.h only work on arguments name and type.

>

> The original tracepoint handler prototype is adjusted by adding a

> __rte_unused for each argument (since emitting macros do nothing

> with them).

> This last part introduces an implementation limit of 15 arguments.

>

> With this change in place, the workaround in dmadev tracepoints can be

> removed.

>

> Signed-off-by: David Marchand <david.marchand@redhat.com<mailto:david.marchand@redhat.com>>



Can I have your opinion and review on this patch?



Thanks.





--

David Marchand
  
Sunil Kumar Kori Feb. 10, 2025, 9:02 a.m. UTC | #5
Hi David,

I tried validating series to see the trace results but babeltrace throws error while reading metadata file and traces can’t be generated.
Can you please have a look into this ?

Thanks.

From: Sunil Kumar Kori
Sent: Friday, February 7, 2025 5:09 PM
To: David Marchand <david.marchand@redhat.com>; Jerin Jacob <jerinj@marvell.com>
Cc: dev@dpdk.org; Chengwen Feng <fengchengwen@huawei.com>; Kevin Laatz <kevin.laatz@intel.com>; Bruce Richardson <bruce.richardson@intel.com>; Tyler Retzlaff <roretzla@linux.microsoft.com>; Andre Muezerie <andremue@linux.microsoft.com>; Thomas Monjalon <thomas@monjalon.net>; Stephen Hemminger <stephen@networkplumber.org>
Subject: RE: [EXTERNAL] Re: [PATCH v2 3/3] trace: fix undefined behavior in register

Hi David,

I will look into this at earliest and provide feedback.

Thanks

From: David Marchand <david.marchand@redhat.com<mailto:david.marchand@redhat.com>>
Sent: Friday, February 7, 2025 2:20 PM
To: Jerin Jacob <jerinj@marvell.com<mailto:jerinj@marvell.com>>; Sunil Kumar Kori <skori@marvell.com<mailto:skori@marvell.com>>
Cc: dev@dpdk.org<mailto:dev@dpdk.org>; Chengwen Feng <fengchengwen@huawei.com<mailto:fengchengwen@huawei.com>>; Kevin Laatz <kevin.laatz@intel.com<mailto:kevin.laatz@intel.com>>; Bruce Richardson <bruce.richardson@intel.com<mailto:bruce.richardson@intel.com>>; Tyler Retzlaff <roretzla@linux.microsoft.com<mailto:roretzla@linux.microsoft.com>>; Andre Muezerie <andremue@linux.microsoft.com<mailto:andremue@linux.microsoft.com>>; Thomas Monjalon <thomas@monjalon.net<mailto:thomas@monjalon.net>>; Stephen Hemminger <stephen@networkplumber.org<mailto:stephen@networkplumber.org>>
Subject: [EXTERNAL] Re: [PATCH v2 3/3] trace: fix undefined behavior in register

Hello Jerin, Sunil, On Thu, Jan 30, 2025 at 3: 59 PM David Marchand <david. marchand@ redhat. com> wrote: > > Registering a tracepoint handler was resulting so far in undefined > behavior at runtime. > > The RTE_TRACE_POINT_REGISTER()


Hello Jerin, Sunil,



On Thu, Jan 30, 2025 at 3:59 PM David Marchand

<david.marchand@redhat.com<mailto:david.marchand@redhat.com>> wrote:

>

> Registering a tracepoint handler was resulting so far in undefined

> behavior at runtime.

>

> The RTE_TRACE_POINT_REGISTER() macro was casting the tracepoint handler

> (which expects arguments) to a void (*)(void).

> At runtime, calling this handler while registering resulted in

> reading the current stack with no relation to this function prototype.

>

> Instead, declare an additional inline _register() handler for each

> tracepoint and make sure that the emitting macros in

> rte_trace_point_register.h only work on arguments name and type.

>

> The original tracepoint handler prototype is adjusted by adding a

> __rte_unused for each argument (since emitting macros do nothing

> with them).

> This last part introduces an implementation limit of 15 arguments.

>

> With this change in place, the workaround in dmadev tracepoints can be

> removed.

>

> Signed-off-by: David Marchand <david.marchand@redhat.com<mailto:david.marchand@redhat.com>>



Can I have your opinion and review on this patch?



Thanks.





--

David Marchand
  
David Marchand Feb. 10, 2025, 9:36 a.m. UTC | #6
On Mon, Feb 10, 2025 at 10:02 AM Sunil Kumar Kori <skori@marvell.com> wrote:
>
> Hi David,
>
> I tried validating series to see the trace results but babeltrace throws error while reading metadata file and traces can’t be generated.
>
> Can you please have a look into this ?

Ok, I see what is wrong, in the dma trace update.
Too bad we don't have something in the CI to catch such issue...

Anyway, do you have comments on this last patch of the series?
  
Jerin Jacob Feb. 10, 2025, 1:37 p.m. UTC | #7
> -----Original Message-----
> From: David Marchand <david.marchand@redhat.com>
> Sent: Thursday, January 30, 2025 8:29 PM
> To: dev@dpdk.org
> Cc: Chengwen Feng <fengchengwen@huawei.com>; Kevin Laatz
> <kevin.laatz@intel.com>; Bruce Richardson <bruce.richardson@intel.com>;
> Jerin Jacob <jerinj@marvell.com>; Sunil Kumar Kori <skori@marvell.com>; Tyler
> Retzlaff <roretzla@linux.microsoft.com>
> Subject: [EXTERNAL] [PATCH v2 3/3] trace: fix undefined behavior in register
> 
> Registering a tracepoint handler was resulting so far in undefined behavior at
> runtime. The RTE_TRACE_POINT_REGISTER() macro was casting the tracepoint
> handler (which expects arguments) to a void (*)(void). At runtime, calling this
> handler while 
> Registering a tracepoint handler was resulting so far in undefined behavior at
> runtime.
> 
> The RTE_TRACE_POINT_REGISTER() macro was casting the tracepoint handler
> (which expects arguments) to a void (*)(void).
> At runtime, calling this handler while registering resulted in reading the current
> stack with no relation to this function prototype.

To reduce the complexity of N number of variable argument, I thought reading.
SP should be fine(Not writing and corrupting it). Looks like some optimization is dmadev
Trace not liking this. I am good with your N arguments scheme.

> 
> +#define
> RTE_TRACE_POINT_ARGS_COUNT_(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,
> _13,_14,_15,N, ...) \
> +	N
> +#define RTE_TRACE_POINT_ARGS_COUNT(...) \
> +
> +RTE_TRACE_POINT_ARGS_COUNT_(__VA_ARGS__,15,14,13,12,11,10,9,8,7,6,5,
> 4,3
> +,2,1,0)
> +
> +#define RTE_TRACE_POINT_ARGS_1(a) __rte_unused a #define
> +RTE_TRACE_POINT_ARGS_2(a, ...) __rte_unused a,
> +RTE_TRACE_POINT_ARGS_1(__VA_ARGS__)
> +#define RTE_TRACE_POINT_ARGS_3(a, ...) __rte_unused a,
> +RTE_TRACE_POINT_ARGS_2(__VA_ARGS__)
> +#define RTE_TRACE_POINT_ARGS_4(a, ...) __rte_unused a,
> +RTE_TRACE_POINT_ARGS_3(__VA_ARGS__)
> +#define RTE_TRACE_POINT_ARGS_5(a, ...) __rte_unused a,
> +RTE_TRACE_POINT_ARGS_4(__VA_ARGS__)
> +#define RTE_TRACE_POINT_ARGS_6(a, ...) __rte_unused a,
> +RTE_TRACE_POINT_ARGS_5(__VA_ARGS__)
> +#define RTE_TRACE_POINT_ARGS_7(a, ...) __rte_unused a,
> +RTE_TRACE_POINT_ARGS_6(__VA_ARGS__)
> +#define RTE_TRACE_POINT_ARGS_8(a, ...) __rte_unused a,
> +RTE_TRACE_POINT_ARGS_7(__VA_ARGS__)
> +#define RTE_TRACE_POINT_ARGS_9(a, ...) __rte_unused a,
> +RTE_TRACE_POINT_ARGS_8(__VA_ARGS__)
> +#define RTE_TRACE_POINT_ARGS_10(a, ...) __rte_unused a,
> +RTE_TRACE_POINT_ARGS_9(__VA_ARGS__)
> +#define RTE_TRACE_POINT_ARGS_11(a, ...) __rte_unused a,
> +RTE_TRACE_POINT_ARGS_10(__VA_ARGS__)
> +#define RTE_TRACE_POINT_ARGS_12(a, ...) __rte_unused a,
> +RTE_TRACE_POINT_ARGS_11(__VA_ARGS__)
> +#define RTE_TRACE_POINT_ARGS_13(a, ...) __rte_unused a,
> +RTE_TRACE_POINT_ARGS_12(__VA_ARGS__)
> +#define RTE_TRACE_POINT_ARGS_14(a, ...) __rte_unused a,
> +RTE_TRACE_POINT_ARGS_13(__VA_ARGS__)
> +#define RTE_TRACE_POINT_ARGS_15(a, ...) __rte_unused a,
> +RTE_TRACE_POINT_ARGS_14(__VA_ARGS__)
> +#define RTE_TRACE_POINT_ARGS_FUNC(a) RTE_TRACE_POINT_ARGS_ ## a
> #define
> +RTE_TRACE_POINT_ARGS_EXPAND(...) __VA_ARGS__ #define
> +RTE_TRACE_POINT_ARGS_(N, ...) \
> +
> 	RTE_TRACE_POINT_ARGS_EXPAND(RTE_TRACE_POINT_ARGS_FUNC(N))
> (__VA_ARGS__)
> +#define RTE_TRACE_POINT_ARGS(...) \
> +	(RTE_TRACE_POINT_ARGS_(RTE_TRACE_POINT_ARGS_COUNT(0,
> __VA_ARGS__),
> +__VA_ARGS__))
> +
> +#define __RTE_TRACE_POINT(_mode, _tp, _args, ...) \ extern
> +rte_trace_point_t __##_tp; \ static __rte_always_inline void _tp _args
> +{ } \ static __rte_always_inline void \ _tp ## _register (void) \ { \
> +	__rte_trace_point_emit_header_##_mode(&__##_tp); \
> +	__VA_ARGS__ \

I have not tested this code, Will this calling __rte_trace_point_emit* version of register?
If not, CTF spec file not generated properly.
https://github.com/DPDK/dpdk/blob/main/lib/eal/include/rte_trace_point_register.h#L35
  
David Marchand Feb. 10, 2025, 2:04 p.m. UTC | #8
On Mon, Feb 10, 2025 at 2:37 PM Jerin Jacob <jerinj@marvell.com> wrote:
> > +
> > +#define __RTE_TRACE_POINT(_mode, _tp, _args, ...) \ extern
> > +rte_trace_point_t __##_tp; \ static __rte_always_inline void _tp _args
> > +{ } \ static __rte_always_inline void \ _tp ## _register (void) \ { \
> > +     __rte_trace_point_emit_header_##_mode(&__##_tp); \
> > +     __VA_ARGS__ \
>
> I have not tested this code, Will this calling __rte_trace_point_emit* version of register?
> If not, CTF spec file not generated properly.
> https://github.com/DPDK/dpdk/blob/main/lib/eal/include/rte_trace_point_register.h#L35

Yes, there are issues with this series that I did not catch until recently.
This will be fixed in a new revision (that will also add babeltrace
calls in CI..).
  

Patch

diff --git a/lib/dmadev/rte_dmadev_trace.h b/lib/dmadev/rte_dmadev_trace.h
index ddf60b9649..9de9b54aad 100644
--- a/lib/dmadev/rte_dmadev_trace.h
+++ b/lib/dmadev/rte_dmadev_trace.h
@@ -22,10 +22,6 @@  extern "C" {
 RTE_TRACE_POINT(
 	rte_dma_trace_info_get,
 	RTE_TRACE_POINT_ARGS(int16_t dev_id, struct rte_dma_info *dev_info),
-#ifdef _RTE_TRACE_POINT_REGISTER_H_
-	struct rte_dma_info __dev_info = {0};
-	dev_info = &__dev_info;
-#endif /* _RTE_TRACE_POINT_REGISTER_H_ */
 	rte_trace_point_emit_i16(dev_id);
 	rte_trace_point_emit_string(dev_info->dev_name);
 	rte_trace_point_emit_u64(dev_info->dev_capa);
@@ -42,10 +38,6 @@  RTE_TRACE_POINT(
 	rte_dma_trace_configure,
 	RTE_TRACE_POINT_ARGS(int16_t dev_id, const struct rte_dma_conf *dev_conf,
 			     int ret),
-#ifdef _RTE_TRACE_POINT_REGISTER_H_
-	const struct rte_dma_conf __dev_conf = {0};
-	dev_conf = &__dev_conf;
-#endif /* _RTE_TRACE_POINT_REGISTER_H_ */
 	rte_trace_point_emit_i16(dev_id);
 	rte_trace_point_emit_u16(dev_conf->nb_vchans);
 	rte_trace_point_emit_u16(dev_conf->priority);
@@ -78,10 +70,6 @@  RTE_TRACE_POINT(
 	rte_dma_trace_vchan_setup,
 	RTE_TRACE_POINT_ARGS(int16_t dev_id, uint16_t vchan,
 			     const struct rte_dma_vchan_conf *conf, int ret),
-#ifdef _RTE_TRACE_POINT_REGISTER_H_
-	const struct rte_dma_vchan_conf __conf = {0};
-	conf = &__conf;
-#endif /* _RTE_TRACE_POINT_REGISTER_H_ */
 	rte_trace_point_emit_i16(dev_id);
 	rte_trace_point_emit_u16(vchan);
 	rte_trace_point_emit_int(conf->direction);
diff --git a/lib/dmadev/rte_dmadev_trace_fp.h b/lib/dmadev/rte_dmadev_trace_fp.h
index 4950f58cd2..106eac24be 100644
--- a/lib/dmadev/rte_dmadev_trace_fp.h
+++ b/lib/dmadev/rte_dmadev_trace_fp.h
@@ -33,10 +33,6 @@  RTE_TRACE_POINT_FP(
 	rte_dma_trace_vchan_status,
 	RTE_TRACE_POINT_ARGS(int16_t dev_id, uint16_t vchan,
 			     enum rte_dma_vchan_status *status, int ret),
-#ifdef _RTE_TRACE_POINT_REGISTER_H_
-	enum rte_dma_vchan_status __status = 0;
-	status = &__status;
-#endif /* _RTE_TRACE_POINT_REGISTER_H_ */
 	rte_trace_point_emit_i16(dev_id);
 	rte_trace_point_emit_u16(vchan);
 	rte_trace_point_emit_int(*status);
@@ -100,12 +96,6 @@  RTE_TRACE_POINT_FP(
 	RTE_TRACE_POINT_ARGS(int16_t dev_id, uint16_t vchan,
 			     const uint16_t nb_cpls, uint16_t *last_idx,
 			     bool *has_error, uint16_t ret),
-#ifdef _RTE_TRACE_POINT_REGISTER_H_
-	uint16_t __last_idx = 0;
-	bool __has_error = false;
-	last_idx = &__last_idx;
-	has_error = &__has_error;
-#endif /* _RTE_TRACE_POINT_REGISTER_H_ */
 	rte_trace_point_emit_i16(dev_id);
 	rte_trace_point_emit_u16(vchan);
 	rte_trace_point_emit_u16(nb_cpls);
@@ -119,10 +109,6 @@  RTE_TRACE_POINT_FP(
 	RTE_TRACE_POINT_ARGS(int16_t dev_id, uint16_t vchan,
 			     const uint16_t nb_cpls, uint16_t *last_idx,
 			     enum rte_dma_status_code *status, uint16_t ret),
-#ifdef _RTE_TRACE_POINT_REGISTER_H_
-	uint16_t __last_idx = 0;
-	last_idx = &__last_idx;
-#endif /* _RTE_TRACE_POINT_REGISTER_H_ */
 	rte_trace_point_emit_i16(dev_id);
 	rte_trace_point_emit_u16(vchan);
 	rte_trace_point_emit_u16(nb_cpls);
diff --git a/lib/eal/include/rte_trace_point.h b/lib/eal/include/rte_trace_point.h
index a162502002..444175f238 100644
--- a/lib/eal/include/rte_trace_point.h
+++ b/lib/eal/include/rte_trace_point.h
@@ -36,6 +36,8 @@  extern "C" {
 /** The tracepoint object. */
 typedef RTE_ATOMIC(uint64_t) rte_trace_point_t;
 
+#ifndef _RTE_TRACE_POINT_REGISTER_H_
+
 /**
  * Macro to define the tracepoint arguments in RTE_TRACE_POINT macro.
 
@@ -53,6 +55,8 @@  _tp _args \
 	__VA_ARGS__ \
 }
 
+#endif /* _RTE_TRACE_POINT_REGISTER_H_ */
+
 /**
  * Create a tracepoint.
  *
diff --git a/lib/eal/include/rte_trace_point_register.h b/lib/eal/include/rte_trace_point_register.h
index 1d6198b32f..ea69daa086 100644
--- a/lib/eal/include/rte_trace_point_register.h
+++ b/lib/eal/include/rte_trace_point_register.h
@@ -18,6 +18,43 @@  extern "C" {
 
 RTE_DECLARE_PER_LCORE(volatile int, trace_point_sz);
 
+#define RTE_TRACE_POINT_ARGS_COUNT_(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,N, ...) \
+	N
+#define RTE_TRACE_POINT_ARGS_COUNT(...) \
+	RTE_TRACE_POINT_ARGS_COUNT_(__VA_ARGS__,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
+
+#define RTE_TRACE_POINT_ARGS_1(a) __rte_unused a
+#define RTE_TRACE_POINT_ARGS_2(a, ...) __rte_unused a, RTE_TRACE_POINT_ARGS_1(__VA_ARGS__)
+#define RTE_TRACE_POINT_ARGS_3(a, ...) __rte_unused a, RTE_TRACE_POINT_ARGS_2(__VA_ARGS__)
+#define RTE_TRACE_POINT_ARGS_4(a, ...) __rte_unused a, RTE_TRACE_POINT_ARGS_3(__VA_ARGS__)
+#define RTE_TRACE_POINT_ARGS_5(a, ...) __rte_unused a, RTE_TRACE_POINT_ARGS_4(__VA_ARGS__)
+#define RTE_TRACE_POINT_ARGS_6(a, ...) __rte_unused a, RTE_TRACE_POINT_ARGS_5(__VA_ARGS__)
+#define RTE_TRACE_POINT_ARGS_7(a, ...) __rte_unused a, RTE_TRACE_POINT_ARGS_6(__VA_ARGS__)
+#define RTE_TRACE_POINT_ARGS_8(a, ...) __rte_unused a, RTE_TRACE_POINT_ARGS_7(__VA_ARGS__)
+#define RTE_TRACE_POINT_ARGS_9(a, ...) __rte_unused a, RTE_TRACE_POINT_ARGS_8(__VA_ARGS__)
+#define RTE_TRACE_POINT_ARGS_10(a, ...) __rte_unused a, RTE_TRACE_POINT_ARGS_9(__VA_ARGS__)
+#define RTE_TRACE_POINT_ARGS_11(a, ...) __rte_unused a, RTE_TRACE_POINT_ARGS_10(__VA_ARGS__)
+#define RTE_TRACE_POINT_ARGS_12(a, ...) __rte_unused a, RTE_TRACE_POINT_ARGS_11(__VA_ARGS__)
+#define RTE_TRACE_POINT_ARGS_13(a, ...) __rte_unused a, RTE_TRACE_POINT_ARGS_12(__VA_ARGS__)
+#define RTE_TRACE_POINT_ARGS_14(a, ...) __rte_unused a, RTE_TRACE_POINT_ARGS_13(__VA_ARGS__)
+#define RTE_TRACE_POINT_ARGS_15(a, ...) __rte_unused a, RTE_TRACE_POINT_ARGS_14(__VA_ARGS__)
+#define RTE_TRACE_POINT_ARGS_FUNC(a) RTE_TRACE_POINT_ARGS_ ## a
+#define RTE_TRACE_POINT_ARGS_EXPAND(...) __VA_ARGS__
+#define RTE_TRACE_POINT_ARGS_(N, ...) \
+	RTE_TRACE_POINT_ARGS_EXPAND(RTE_TRACE_POINT_ARGS_FUNC(N))(__VA_ARGS__)
+#define RTE_TRACE_POINT_ARGS(...) \
+	(RTE_TRACE_POINT_ARGS_(RTE_TRACE_POINT_ARGS_COUNT(0, __VA_ARGS__), __VA_ARGS__))
+
+#define __RTE_TRACE_POINT(_mode, _tp, _args, ...) \
+extern rte_trace_point_t __##_tp; \
+static __rte_always_inline void _tp _args { } \
+static __rte_always_inline void \
+_tp ## _register (void) \
+{ \
+	__rte_trace_point_emit_header_##_mode(&__##_tp); \
+	__VA_ARGS__ \
+}
+
 #define RTE_TRACE_POINT_REGISTER(trace, name) \
 rte_trace_point_t __rte_section("__rte_trace_point") __##trace; \
 static const char __##trace##_name[] = RTE_STR(name); \
@@ -26,7 +63,7 @@  RTE_INIT(trace##_init) \
 	if (!rte_trace_feature_is_enabled()) \
 		return; \
 	__rte_trace_point_register(&__##trace, __##trace##_name, \
-		(void (*)(void)) trace); \
+		trace ## _register); \
 }
 
 #define __rte_trace_point_emit_header_generic(t) \
@@ -37,21 +74,18 @@  RTE_INIT(trace##_init) \
 
 #define __rte_trace_point_emit(in, type) \
 do { \
-	RTE_SET_USED(in); \
 	__rte_trace_point_emit_field(sizeof(type), RTE_STR(in), \
 		RTE_STR(type)); \
 } while (0)
 
 #define rte_trace_point_emit_string(in) \
 do { \
-	RTE_SET_USED(in); \
 	__rte_trace_point_emit_field(__RTE_TRACE_EMIT_STRING_LEN_MAX, \
 		RTE_STR(in)"[32]", "string_bounded_t"); \
 } while (0)
 
 #define rte_trace_point_emit_blob(in, len) \
 do { \
-	RTE_SET_USED(in); \
 	__rte_trace_point_emit(len, uint8_t); \
 	__rte_trace_point_emit_field(RTE_TRACE_BLOB_LEN_MAX, \
 		RTE_STR(in)"[" RTE_STR(RTE_TRACE_BLOB_LEN_MAX)"]", \