diff mbox series

[livepatch-build-tools,part2,v2,6/6] create-diff-object: Do not include all .rodata sections

Message ID 20190808123916.8706-1-wipawel@amazon.de (mailing list archive)
State New, archived
Headers show
Series None | expand

Commit Message

Wieczorkiewicz, Pawel Aug. 8, 2019, 12:39 p.m. UTC
Older versions of GCC did not split .rodata.str sections by function.
Because of that, the entire section was always included.
The livepatch-build-tools commit [1] fixed patch creation and kept
including all .rodata.str sections, in order to maintain existing
behavior for GCC 6.1+.
This means all .rodata.str sections are always included by default,
regardless of whether they are needed or not.

During stacked hotpatch builds it leads to unnecessary accumulation of
the .rodata.str sections as each and every consecutive hotpatch module
contains all the .rodata.str sections of previous modules.

To prevent this situation, mark the .rodata.str sections for inclusion
only if they are referenced by any of the current hotpatch symbols (or
a corresponding RELA section).

Extend patchability verification to detect all non-standard, non-rela,
non-debug and non-special sections that are not referenced by any of
the symbols or RELA sections.

[1] 2af6f1aa6233 Fix patch creation with GCC 6.1+

Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Bjoern Doebel <doebel@amazon.de>
Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
---
v2:
* Made the commit message more precise and accurate (based on
  Ross' comments to the v1 patch)
* Kept lines limited to 80 chars
---
 create-diff-object.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

Comments

Ross Lagerwall Aug. 16, 2019, 9:57 a.m. UTC | #1
On 8/8/19 1:39 PM, Pawel Wieczorkiewicz wrote:
> Older versions of GCC did not split .rodata.str sections by function.
> Because of that, the entire section was always included.
> The livepatch-build-tools commit [1] fixed patch creation and kept
> including all .rodata.str sections, in order to maintain existing
> behavior for GCC 6.1+.
> This means all .rodata.str sections are always included by default,
> regardless of whether they are needed or not.
> 
> During stacked hotpatch builds it leads to unnecessary accumulation of
> the .rodata.str sections as each and every consecutive hotpatch module
> contains all the .rodata.str sections of previous modules.
> 
> To prevent this situation, mark the .rodata.str sections for inclusion
> only if they are referenced by any of the current hotpatch symbols (or
> a corresponding RELA section).
> 
> Extend patchability verification to detect all non-standard, non-rela,
> non-debug and non-special sections that are not referenced by any of
> the symbols or RELA sections.
> 
> [1] 2af6f1aa6233 Fix patch creation with GCC 6.1+
> 
> Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
> Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
> Reviewed-by: Bjoern Doebel <doebel@amazon.de>
> Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
> ---
> v2:
> * Made the commit message more precise and accurate (based on
>    Ross' comments to the v1 patch)
> * Kept lines limited to 80 chars
> ---
>   create-diff-object.c | 30 ++++++++++++++++++++++++++++--
>   1 file changed, 28 insertions(+), 2 deletions(-)
> 
> diff --git a/create-diff-object.c b/create-diff-object.c
> index 8365af0..4252175 100644
> --- a/create-diff-object.c
> +++ b/create-diff-object.c
> @@ -1350,8 +1350,7 @@ static void kpatch_include_standard_elements(struct kpatch_elf *kelf)
>   
>   	list_for_each_entry(sec, &kelf->sections, list) {
>   		/* include these sections even if they haven't changed */
> -		if (is_standard_section(sec) ||
> -		    should_include_str_section(sec->name)) {
> +		if (is_standard_section(sec)) {
>   			sec->include = 1;
>   			if (sec->secsym)
>   				sec->secsym->include = 1;
> @@ -1362,6 +1361,20 @@ static void kpatch_include_standard_elements(struct kpatch_elf *kelf)
>   	list_entry(kelf->symbols.next, struct symbol, list)->include = 1;
>   }
>   
> +static void kpatch_include_standard_string_elements(struct kpatch_elf *kelf)
> +{
> +	struct section *sec;
> +
> +	list_for_each_entry(sec, &kelf->sections, list) {
> +		if (should_include_str_section(sec->name) &&
> +		    is_referenced_section(sec, kelf)) {
> +			sec->include = 1;
> +			if (sec->secsym)
> +				sec->secsym->include = 1;
> +		}
> +	}
> +}
> +
>   #define inc_printf(fmt, ...) \
>   	log_debug("%*s" fmt, recurselevel, "", ##__VA_ARGS__);
This patch looks good. There is a comment at the top of 
should_include_str_section() which should probably be updated as well:

/*
  * String sections are always included even if unchanged.
  * The format is either:
  * .rodata.<func>.str1.[0-9]+ (new in GCC 6.1.0)
  * or .rodata.str1.[0-9]+ (older versions of GCC)
  * For the new format we could be smarter and only include the needed
  * strings sections.
  */

In fact, it is probably a good idea to rename the function to something 
like "is_rodata_str_section()" since this more accurately describes what 
it does now.

Thanks,
Wieczorkiewicz, Pawel Aug. 16, 2019, 12:08 p.m. UTC | #2
> On 16. Aug 2019, at 11:57, Ross Lagerwall <ross.lagerwall@citrix.com> wrote:
> 
> On 8/8/19 1:39 PM, Pawel Wieczorkiewicz wrote:
>> 

…snip...

>>  #define inc_printf(fmt, ...) \
>>  	log_debug("%*s" fmt, recurselevel, "", ##__VA_ARGS__);
> This patch looks good. There is a comment at the top of should_include_str_section() which should probably be updated as well:
> 
> /*
> * String sections are always included even if unchanged.
> * The format is either:
> * .rodata.<func>.str1.[0-9]+ (new in GCC 6.1.0)
> * or .rodata.str1.[0-9]+ (older versions of GCC)
> * For the new format we could be smarter and only include the needed
> * strings sections.
> */
> 

Oh yes, right. Let me update the comment. Thanks!

> In fact, it is probably a good idea to rename the function to something like "is_rodata_str_section()" since this more accurately describes what it does now.

ACK, will do.

> 
> Thanks,
> --
> Ross Lagerwall


Best Regards,
Pawel Wieczorkiewicz
Amazon Development Center Germany GmbH
Krausenstr. 38
10117 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Ralf Herbrich
Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B
Sitz: Berlin
Ust-ID: DE 289 237 879
diff mbox series

Patch

diff --git a/create-diff-object.c b/create-diff-object.c
index 8365af0..4252175 100644
--- a/create-diff-object.c
+++ b/create-diff-object.c
@@ -1350,8 +1350,7 @@  static void kpatch_include_standard_elements(struct kpatch_elf *kelf)
 
 	list_for_each_entry(sec, &kelf->sections, list) {
 		/* include these sections even if they haven't changed */
-		if (is_standard_section(sec) ||
-		    should_include_str_section(sec->name)) {
+		if (is_standard_section(sec)) {
 			sec->include = 1;
 			if (sec->secsym)
 				sec->secsym->include = 1;
@@ -1362,6 +1361,20 @@  static void kpatch_include_standard_elements(struct kpatch_elf *kelf)
 	list_entry(kelf->symbols.next, struct symbol, list)->include = 1;
 }
 
+static void kpatch_include_standard_string_elements(struct kpatch_elf *kelf)
+{
+	struct section *sec;
+
+	list_for_each_entry(sec, &kelf->sections, list) {
+		if (should_include_str_section(sec->name) &&
+		    is_referenced_section(sec, kelf)) {
+			sec->include = 1;
+			if (sec->secsym)
+				sec->secsym->include = 1;
+		}
+	}
+}
+
 #define inc_printf(fmt, ...) \
 	log_debug("%*s" fmt, recurselevel, "", ##__VA_ARGS__);
 
@@ -1541,6 +1554,17 @@  static void kpatch_verify_patchability(struct kpatch_elf *kelf)
 			errs++;
 		}
 
+		if (sec->include) {
+			if (!is_standard_section(sec) && !is_rela_section(sec) &&
+			    !is_debug_section(sec) && !is_special_section(sec)) {
+				if (!is_referenced_section(sec, kelf)) {
+					log_normal("section %s included, but not referenced\n",
+						   sec->name);
+					errs++;
+				}
+			}
+		}
+
 		/*
 		 * ensure we aren't including .data.* or .bss.*
 		 * (.data.unlikely is ok b/c it only has __warned vars)
@@ -2072,6 +2096,8 @@  int main(int argc, char *argv[])
 	kpatch_include_debug_sections(kelf_patched);
 	log_debug("Include hook elements\n");
 	kpatch_include_hook_elements(kelf_patched);
+	log_debug("Include standard string elements\n");
+	kpatch_include_standard_string_elements(kelf_patched);
 	log_debug("Include new globals\n");
 	new_globals_exist = kpatch_include_new_globals(kelf_patched);
 	log_debug("new_globals_exist = %d\n", new_globals_exist);