On Mon, 2018-07-30 at 10:51 -0400, David Malcolm wrote: > On Sun, 2018-07-29 at 13:41 -0700, Joe Perches wrote: > > I would like to implement a gcc plugin that can compress an > > __attribute__((format(printf, x, y))) const char array before > > storage so that the formats can be size reduced when stored and > > expanded appropriately before use. > > > > As this is the first plugin I am trying to implement, I'm a bit > > lost in details and I am looking for guidance. > > > > Basically: > > > > Take the printf_format_type CONST_DECL format being verified by > > gcc/c-format-main.c and after the verification, compress the > > format and its length before storage into its .read_only section. > > > > A custom vsnprintf routine would expand the compressed format to > > its original form before use. > > > > All tips to necessary gcc plugin implementation details appreciated. > > If I understand your idea correctly, you're wanting to write a plugin > that turns something like: > > printf ("some format string %s %i %s etc\n", arg1, arg2, arg3); > > into something like: > > your_custom_printf ("cmprssd_frmt_strng", arg1, arg2, arg3);
Thank you for the reply. More or less, but not quite. The idea is to use a specific __attribute__, here format(printf, x, y), although it could be another custom attribute, to identify which strings to store in some compressed manner. I want to compress some format strings and keep gcc's ability to verify format and arg compatibility while possibly duplicating storage for identical strings. For example, this should store 2 strings in .rodata... o original uncompressed "fmt: '%s'\n" o and the compressed equivalent used only in the first compress_fmt call for the first argument. $ cat t_format.c __attribute__((format(printf, 1, 2))) void compress_fmt(const char *fmt, ...); void original_fmt(const char *fmt, ...); #define FMT "fmt: '%s'\n" void foo(void) { const char *fmt = FMT; // uncompressed compress_fmt(FMT, fmt); // compressed and uncompressed original_fmt(FMT, fmt); // uncompressed compress_fmt(fmt, fmt); // uncompressed } $