@@ -1448,6 +1448,31 @@ static void kpatch_print_changes(struct kpatch_elf *kelf)
}
}
+static inline int get_section_entry_size(const struct section *sec, struct kpatch_elf *kelf)
+{
+ int entry_size;
+
+ /*
+ * Base sections typically do not define fixed size elements.
+ * Detect section's element size in case it's a special section.
+ * Otherwise, skip it due to an unknown sh_entsize.
+ */
+ entry_size = sec->sh.sh_entsize;
+ if (entry_size == 0) {
+ struct special_section *special;
+
+ /* Find special section group_size. */
+ for (special = special_sections; special->name; special++) {
+ /* Match sections starting with special->name prefix */
+ if (!strncmp(sec->name, special->name, strlen(special->name))) {
+ return special->group_size(kelf, 0);
+ }
+ }
+ }
+
+ return entry_size;
+}
+
static void kpatch_verify_patchability(struct kpatch_elf *kelf)
{
struct section *sec;
@@ -1471,6 +1496,41 @@ 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++;
+ }
+ }
+
+ /* Check if a RELA section does not contain any entries with
+ * undefined symbols (STN_UNDEF). This situation can happen
+ * when a section is copied over from its original object to
+ * a patched object, but various symbols related to the section
+ * are not copied along.
+ */
+ if (is_rela_section(sec)) {
+ int offset, entry_size = get_section_entry_size(sec, kelf);
+ struct rela *rela;
+
+ for ( offset = 0; offset < sec->base->data->d_size && entry_size; offset += entry_size ) {
+ list_for_each_entry(rela, &sec->relas, list) {
+ if (rela->offset < offset || rela->offset >= offset + entry_size)
+ continue;
+
+ if ((GELF_R_SYM(rela->rela.r_info) == STN_UNDEF) ||
+ (!rela->sym->include && (rela->sym->status == SAME))) {
+ log_normal("section %s has an entry with a STN_UNDEF symbol: %s\n",
+ sec->name, rela->sym->name ? rela->sym->name : "none");
+ errs++;
+ }
+ }
+ }
+ }
+ }
+
/*
* ensure we aren't including .data.* or .bss.*
* (.data.unlikely is ok b/c it only has __warned vars)