syscare/0043-upatch-manage-fix-find-upatch-region-bug.patch
renoseven aaca4c9c5f update to 1.2.1-10
Signed-off-by: renoseven <dev@renoseven.net>
2024-08-16 16:44:21 +08:00

262 lines
8.6 KiB
Diff

From d0bd28247e41b9cec11d61f0d1b6a86f78a4dabd Mon Sep 17 00:00:00 2001
From: ningyu <405888464@qq.com>
Date: Fri, 9 Aug 2024 14:33:01 +0800
Subject: [PATCH] upatch-manage: fix find upatch region bug
Signed-off-by: ningyu <405888464@qq.com>
---
upatch-manage/arch/aarch64/process.h | 28 ---------
upatch-manage/arch/x86_64/process.h | 28 ---------
upatch-manage/upatch-patch.c | 2 +-
upatch-manage/upatch-process.c | 91 ++++++----------------------
upatch-manage/upatch-process.h | 6 +-
5 files changed, 23 insertions(+), 132 deletions(-)
delete mode 100644 upatch-manage/arch/aarch64/process.h
delete mode 100644 upatch-manage/arch/x86_64/process.h
diff --git a/upatch-manage/arch/aarch64/process.h b/upatch-manage/arch/aarch64/process.h
deleted file mode 100644
index 8acf04b..0000000
--- a/upatch-manage/arch/aarch64/process.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * upatch-manage
- * Copyright (C) 2024 Huawei Technologies Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef __PROCESS__
-#define __PROCESS__
-
-#ifndef MAX_DISTANCE
-#define MAX_DISTANCE 0x8000000
-#endif
-
-#endif
\ No newline at end of file
diff --git a/upatch-manage/arch/x86_64/process.h b/upatch-manage/arch/x86_64/process.h
deleted file mode 100644
index 5de8fc3..0000000
--- a/upatch-manage/arch/x86_64/process.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * upatch-manage
- * Copyright (C) 2024 Huawei Technologies Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef __PROCESS__
-#define __PROCESS__
-
-#ifndef MAX_DISTANCE
-#define MAX_DISTANCE 0x80000000
-#endif
-
-#endif
\ No newline at end of file
diff --git a/upatch-manage/upatch-patch.c b/upatch-manage/upatch-patch.c
index 8a1ad41..c9fcbc9 100644
--- a/upatch-manage/upatch-patch.c
+++ b/upatch-manage/upatch-patch.c
@@ -271,7 +271,7 @@ static void *upatch_alloc(struct object_file *obj, size_t sz)
unsigned long addr;
struct vm_hole *hole = NULL;
- addr = object_find_patch_region_nolimit(obj, sz, &hole);
+ addr = object_find_patch_region(obj, sz, &hole);
if (!addr)
return NULL;
diff --git a/upatch-manage/upatch-process.c b/upatch-manage/upatch-process.c
index 84ec030..f4033cb 100644
--- a/upatch-manage/upatch-process.c
+++ b/upatch-manage/upatch-process.c
@@ -33,7 +33,6 @@
#include "list.h"
#include "log.h"
-#include "process.h"
#include "upatch-common.h"
#include "upatch-elf.h"
#include "upatch-process.h"
@@ -804,8 +803,9 @@ int vm_hole_split(struct vm_hole *hole, unsigned long alloc_start,
* and the next hole as a right candidate. Pace through them until there is
* enough space in the hole for the patch.
*
- * Since holes can be much larger than 2GiB take extra caution to allocate
- * patch region inside the (-2GiB, +2GiB) range from the original object.
+ * Due to relocation constraints, the hole position should be whin 4GB range
+ * from the obj.
+ * eg: R_AARCH64_ADR_GOT_PAGE
*/
unsigned long object_find_patch_region(struct object_file *obj, size_t memsize,
struct vm_hole **hole)
@@ -813,96 +813,41 @@ unsigned long object_find_patch_region(struct object_file *obj, size_t memsize,
struct list_head *head = &obj->proc->vmaholes;
struct vm_hole *left_hole = obj->previous_hole;
struct vm_hole *right_hole = next_hole(left_hole, head);
- unsigned long max_distance = MAX_DISTANCE;
+ unsigned long region_start = 0;
struct obj_vm_area *sovma;
-
unsigned long obj_start, obj_end;
- unsigned long region_start = 0, region_end = 0;
-
- log_debug("Looking for patch region for '%s'...\n", obj->name);
sovma = list_first_entry(&obj->vma, struct obj_vm_area, list);
obj_start = sovma->inmem.start;
sovma = list_entry(obj->vma.prev, struct obj_vm_area, list);
obj_end = sovma->inmem.end;
- max_distance -= memsize;
-
- /* TODO carefully check for the holes laying between obj_start and
- * obj_end, i.e. just after the executable segment of an executable
- */
- while (left_hole != NULL && right_hole != NULL) {
- if (right_hole != NULL &&
- right_hole->start - obj_start > max_distance)
- right_hole = NULL;
- else if (hole_size(right_hole) > memsize) {
- region_start = right_hole->start;
- region_end = (right_hole->end - obj_start) <=
- max_distance ?
- right_hole->end - memsize :
- obj_start + max_distance;
- *hole = right_hole;
- break;
- } else
- right_hole = next_hole(right_hole, head);
-
- if (left_hole != NULL &&
- obj_end - left_hole->end > max_distance)
- left_hole = NULL;
- else if (hole_size(left_hole) > memsize) {
- region_start = (obj_end - left_hole->start) <=
- max_distance ?
- left_hole->start :
- obj_end > max_distance ?
- obj_end - max_distance :
- 0;
- region_end = left_hole->end - memsize;
- *hole = left_hole;
- break;
- } else
- left_hole = prev_hole(left_hole, head);
- }
-
- if (region_start == region_end) {
- log_error("Cannot find suitable region for patch '%s'\n", obj->name);
- return -1UL;
- }
-
- region_start = (region_start >> (unsigned long)PAGE_SHIFT) << (unsigned long)PAGE_SHIFT;
- log_debug("Found patch region for '%s' at 0x%lx\n", obj->name,
- region_start);
-
- return region_start;
-}
-unsigned long object_find_patch_region_nolimit(struct object_file *obj, size_t memsize,
- struct vm_hole **hole)
-{
- struct list_head *head = &obj->proc->vmaholes;
- struct vm_hole *left_hole = obj->previous_hole;
- struct vm_hole *right_hole = next_hole(left_hole, head);
- unsigned long region_start = 0;
-
log_debug("Looking for patch region for '%s'...\n", obj->name);
- while (right_hole != NULL) {
+ while (right_hole != NULL || left_hole != NULL) {
if (hole_size(right_hole) > memsize) {
*hole = right_hole;
+ region_start = right_hole->start;
+ if (region_start + memsize - obj_start > MAX_DISTANCE) {
+ continue;
+ }
goto found;
- } else
- right_hole = next_hole(right_hole, head);
-
- while (left_hole != NULL)
+ }
if (hole_size(left_hole) > memsize) {
*hole = left_hole;
+ region_start = left_hole->end - memsize;
+ if (obj_end - region_start > MAX_DISTANCE) {
+ continue;
+ }
goto found;
- } else
- left_hole = prev_hole(left_hole, head);
+ }
+ right_hole = next_hole(right_hole, head);
+ left_hole = prev_hole(left_hole, head);
}
-
log_error("Cannot find suitable region for patch '%s'\n", obj->name);
return -1UL;
found:
- region_start = ((*hole)->start >> PAGE_SHIFT) << PAGE_SHIFT;
+ region_start = (region_start >> PAGE_SHIFT) << PAGE_SHIFT;
log_debug("Found patch region for '%s' 0xat %lx\n", obj->name,
region_start);
diff --git a/upatch-manage/upatch-process.h b/upatch-manage/upatch-process.h
index be44cb5..fdbd752 100644
--- a/upatch-manage/upatch-process.h
+++ b/upatch-manage/upatch-process.h
@@ -33,6 +33,10 @@
#define ELFMAG "\177ELF"
#define SELFMAG 4
+#ifndef MAX_DISTANCE
+#define MAX_DISTANCE (1UL << 32)
+#endif
+
enum {
MEM_READ,
MEM_WRITE,
@@ -143,7 +147,5 @@ int vm_hole_split(struct vm_hole *, unsigned long, unsigned long);
unsigned long object_find_patch_region(struct object_file *, size_t,
struct vm_hole **);
-unsigned long object_find_patch_region_nolimit(struct object_file *, size_t,
- struct vm_hole **);
#endif
--
2.34.1