diff --git a/0001-fix-kernel-patch-ACCEPTED-change-to-DEACTIVED-after-.patch b/0001-fix-kernel-patch-ACCEPTED-change-to-DEACTIVED-after-.patch index 6870278c75898bc3f7657a89d4e38c17598aefbc..0247673b90e641fe2780e6f09b778bbe56cc3974 100644 --- a/0001-fix-kernel-patch-ACCEPTED-change-to-DEACTIVED-after-.patch +++ b/0001-fix-kernel-patch-ACCEPTED-change-to-DEACTIVED-after-.patch @@ -22,5 +22,5 @@ index 22efa93..fd5160c 100644 .map_err(|e| anyhow!("Kpatch: {}", std::io::Error::from(e))) } -- -2.34.1 +2.43.0 diff --git a/0002-fix-some-clean-code-problem.patch b/0002-fix-some-clean-code-problem.patch index 7f14c6071b177d7242b4128a4c39c60bc9f41834..3532244f8d5dc7a69f8d2c0c6d51023272a3e077 100644 --- a/0002-fix-some-clean-code-problem.patch +++ b/0002-fix-some-clean-code-problem.patch @@ -93,5 +93,5 @@ index d9a356b..7880eed 100644 + (unsigned long)insn->kaddr); +} -- -2.34.1 +2.43.0 diff --git a/0003-syscared-fix-active-accepted-patch-failure-issue.patch b/0003-syscared-fix-active-accepted-patch-failure-issue.patch index 21beac2375feb2f2269d3ae81e4c396a8ca5e503..5061b530cb85101e7c00cb3fb548f303fbcb4727 100644 --- a/0003-syscared-fix-active-accepted-patch-failure-issue.patch +++ b/0003-syscared-fix-active-accepted-patch-failure-issue.patch @@ -45,5 +45,5 @@ index 3a724db..a17703c 100644 impl Drop for PatchManager { -- -2.34.1 +2.43.0 diff --git a/0004-upatch-helper-fix-object-upatch-id-duplicated-issue.patch b/0004-upatch-helper-fix-object-upatch-id-duplicated-issue.patch index e491876bc4a5098d56ef4855febbbc058719b595..2eaf1eff5e9fe3c759fa0d299c0d16f9d4d9dffc 100644 --- a/0004-upatch-helper-fix-object-upatch-id-duplicated-issue.patch +++ b/0004-upatch-helper-fix-object-upatch-id-duplicated-issue.patch @@ -46,5 +46,5 @@ index d98b167..303088c 100644 } -- -2.34.1 +2.43.0 diff --git a/0005-syscare-build-update-README.md.patch b/0005-syscare-build-update-README.md.patch index 54860be1723ab05207490851f649bf07db708c2a..b6089157882e959d5e4716a8bb643c8ab7cf3725 100644 --- a/0005-syscare-build-update-README.md.patch +++ b/0005-syscare-build-update-README.md.patch @@ -166,5 +166,5 @@ index e0cf66e..1f05c74 100644 -rw-r--r--. 1 dev dev 186M Nov 12 00:00 kernel-5.10.0-60.80.0.104.oe2203-HP001-1-1.x86_64.src.rpm -rw-r--r--. 1 dev dev 11K Nov 12 00:00 patch-kernel-5.10.0-60.80.0.104.oe2203-HP001-1-1.x86_64.rpm -- -2.34.1 +2.43.0 diff --git a/0006-syscared-support-saving-restoring-patch-status-by-op.patch b/0006-syscared-support-saving-restoring-patch-status-by-op.patch index 9699cd80093ffc95f39362fcd81971f1243417ed..98a29a064c5304c229880e18da92fe7501326fc0 100644 --- a/0006-syscared-support-saving-restoring-patch-status-by-op.patch +++ b/0006-syscared-support-saving-restoring-patch-status-by-op.patch @@ -158,5 +158,5 @@ index a17703c..48c583a 100644 } -- -2.34.1 +2.43.0 diff --git a/0007-project-update-Cargo.lock.patch b/0007-project-update-Cargo.lock.patch index 4649e6cac8cd04475e758827ec6c705344ad7af1..ab73a334fa853852e4e7f8bdf8d9088b13693702 100644 --- a/0007-project-update-Cargo.lock.patch +++ b/0007-project-update-Cargo.lock.patch @@ -30,5 +30,5 @@ index 48ca061..30f2015 100644 [[package]] -- -2.34.1 +2.43.0 diff --git a/0008-all-remove-signal-handler.patch b/0008-all-remove-signal-handler.patch index d5980eacdf00d4ad9cb2a3c19648e51cc07c7c70..1ee216106a938fea2619f46e25cd8cdb6652e1b7 100644 --- a/0008-all-remove-signal-handler.patch +++ b/0008-all-remove-signal-handler.patch @@ -1,4 +1,4 @@ -From 5daf18084f8d2865db24b6627d2d28d9234bcf5c Mon Sep 17 00:00:00 2001 +From f41f2c12673a1a5a25fd1f149220836c93d3b677 Mon Sep 17 00:00:00 2001 From: renoseven Date: Mon, 10 Feb 2025 10:49:49 +0800 Subject: [PATCH] all: remove signal handler @@ -70,5 +70,5 @@ index 77b256a..09f907b 100644 args, logger, -- -2.34.1 +2.43.0 diff --git a/0009-project-update-Cargo.lock.patch b/0009-project-update-Cargo.lock.patch index d1bcc1844d402762201fcb7df04cf26c4c47d53e..eb1abaf613c26fe6431d2ee5b322f5ba2b690524 100644 --- a/0009-project-update-Cargo.lock.patch +++ b/0009-project-update-Cargo.lock.patch @@ -1,4 +1,4 @@ -From bed35b84e7cbeaafd16c9c01650243ae548a9c14 Mon Sep 17 00:00:00 2001 +From 276ea96f44628f4ccc8dc43962502d414a24e80b Mon Sep 17 00:00:00 2001 From: renoseven Date: Mon, 10 Feb 2025 11:49:40 +0800 Subject: [PATCH] project: update Cargo.lock @@ -62,5 +62,5 @@ index 30f2015..6ae9f36 100644 name = "windows-targets" version = "0.48.5" -- -2.34.1 +2.43.0 diff --git a/0010-syscare-remove-working-directory-check.patch b/0010-syscare-remove-working-directory-check.patch index a4a9e1a056864bc895c98bae8bd0859fb55b1ab2..978a0339e248049942bcb8670caa9b863a18ac12 100644 --- a/0010-syscare-remove-working-directory-check.patch +++ b/0010-syscare-remove-working-directory-check.patch @@ -1,4 +1,4 @@ -From 707475a7361b6f16ca2b9e62f222b1982a57e506 Mon Sep 17 00:00:00 2001 +From 1f34ba0818560a0da448e9034876082e9a30a129 Mon Sep 17 00:00:00 2001 From: renoseven Date: Mon, 10 Feb 2025 14:21:29 +0800 Subject: [PATCH] syscare: remove working directory check @@ -48,5 +48,5 @@ index 4f034a0..5e7299d 100644 impl std::fmt::Display for Arguments { -- -2.34.1 +2.43.0 diff --git a/0011-all-fix-cargo-clippy-warnings.patch b/0011-all-fix-cargo-clippy-warnings.patch index 3f8ef8e36611a31784b056dbb5ed28b65d10c344..c3893dc03f44e3e27e6a4f0100f9c730cb4a7fd6 100644 --- a/0011-all-fix-cargo-clippy-warnings.patch +++ b/0011-all-fix-cargo-clippy-warnings.patch @@ -1,4 +1,4 @@ -From 2af03514afcc797cac3125c7b04ee0f5eae43aa0 Mon Sep 17 00:00:00 2001 +From d0cc1a3324f2f82f08297b4dcea4a3d9387b203c Mon Sep 17 00:00:00 2001 From: renoseven Date: Mon, 10 Feb 2025 10:29:00 +0800 Subject: [PATCH] all: fix cargo clippy warnings @@ -158,5 +158,5 @@ index e8c7cdf..a6e8fb9 100644 type Offset = R::Offset; -- -2.34.1 +2.43.0 diff --git a/0012-upatch-diff-format-code.patch b/0012-upatch-diff-format-code.patch index 5620e49910ab966000ed07e12dcb53c9ceddeecc..b7f88a246c505a687657e9f1ba616fb8cf9cf545 100644 --- a/0012-upatch-diff-format-code.patch +++ b/0012-upatch-diff-format-code.patch @@ -1,4 +1,4 @@ -From 47ac3ae5e1e6cb790df0f24433e2d8071ef7541f Mon Sep 17 00:00:00 2001 +From 5ed5d301e6cb5b0c6df8071e988fda7e0deb90df Mon Sep 17 00:00:00 2001 From: renoseven Date: Sat, 15 Feb 2025 17:05:06 +0800 Subject: [PATCH] upatch-diff: format code @@ -8353,5 +8353,5 @@ index 5e2abce..ec0148f 100644 \ No newline at end of file +#endif /* __UPATCH_PATCH_H_ */ -- -2.34.1 +2.43.0 diff --git a/0013-upatch-manage-format-code.patch b/0013-upatch-manage-format-code.patch index f915b9c6cdc157ae36af7bab4b75d5c02d493eee..827436dd9594b97aa3c6355db060b9fb656b27ae 100644 --- a/0013-upatch-manage-format-code.patch +++ b/0013-upatch-manage-format-code.patch @@ -1,4 +1,4 @@ -From 9356dfedc5a242df73febf40eccb428347c3a7ce Mon Sep 17 00:00:00 2001 +From d608ecb58f076aacf3c6da115f6933a48a2b3925 Mon Sep 17 00:00:00 2001 From: renoseven Date: Mon, 17 Feb 2025 15:41:50 +0800 Subject: [PATCH] upatch-manage: format code @@ -8176,5 +8176,5 @@ index 96b8a51..49be6e3 100644 + upatch_action_t action); +#endif -- -2.34.1 +2.43.0 diff --git a/0014-upatch-manage-remove-build-id-check.patch b/0014-upatch-manage-remove-build-id-check.patch index ce549f7846421175dd791a7c1418c2fe311d108e..f0f922fe080fbbce068d9670610007796f3efa9d 100644 --- a/0014-upatch-manage-remove-build-id-check.patch +++ b/0014-upatch-manage-remove-build-id-check.patch @@ -1,4 +1,4 @@ -From a54cbc3202a1409c040e988043310d4d09d91bc8 Mon Sep 17 00:00:00 2001 +From 5dbcd7bfb65297cf9f49a6a6f1eed5e8ad282cfe Mon Sep 17 00:00:00 2001 From: renoseven Date: Tue, 18 Feb 2025 15:48:28 +0800 Subject: [PATCH] upatch-manage: remove build id check @@ -84,5 +84,5 @@ index 18e0d2c..2193f9a 100644 bool is_note_section(GElf_Word); -- -2.34.1 +2.43.0 diff --git a/0015-upatch-diff-print-detail-changes.patch b/0015-upatch-diff-print-detail-changes.patch index 92e76e4525caa2e760e69f9134ab54380bde7104..363a37749e28fc3f5b86d0b3636586ecd33c2cff 100644 --- a/0015-upatch-diff-print-detail-changes.patch +++ b/0015-upatch-diff-print-detail-changes.patch @@ -1,4 +1,4 @@ -From b923bc814e0863fe61456fe6a40bd8b2be2be993 Mon Sep 17 00:00:00 2001 +From 1b46259d34d45135b86712699d59d54e662a067b Mon Sep 17 00:00:00 2001 From: renoseven Date: Tue, 18 Feb 2025 16:03:26 +0800 Subject: [PATCH] upatch-diff: print detail changes @@ -92,5 +92,5 @@ index 677b8bc..9d2641a 100644 void upatch_dump_kelf(struct upatch_elf *uelf) -- -2.34.1 +2.43.0 diff --git a/0016-upatch-diff-ignore-useless-sections.patch b/0016-upatch-diff-ignore-useless-sections.patch index e46b30968f9457c0dfba0153086a39e762cdeb9a..88dc5ee852f4b263a83791ee7c6c60ec939fc9b1 100644 --- a/0016-upatch-diff-ignore-useless-sections.patch +++ b/0016-upatch-diff-ignore-useless-sections.patch @@ -1,4 +1,4 @@ -From c3df3930682334433437ee58a4e8dce46d956929 Mon Sep 17 00:00:00 2001 +From e7bcedcfd2d7f5578de82b426e52cb307596ec98 Mon Sep 17 00:00:00 2001 From: renoseven Date: Tue, 18 Feb 2025 17:04:46 +0800 Subject: [PATCH] upatch-diff: ignore useless sections @@ -78,5 +78,5 @@ index f5a48da..bc2c1ac 100644 do { \ (_new) = calloc(1, sizeof(*(_new))); \ -- -2.34.1 +2.43.0 diff --git a/0017-upatch-manage-enrich-log-output.patch b/0017-upatch-manage-enrich-log-output.patch index 4772eba31dea19484fc7958e84cf5fc61d6cd194..4b803420ae1d9f82c898b4856e04ac0768d6a0b0 100644 --- a/0017-upatch-manage-enrich-log-output.patch +++ b/0017-upatch-manage-enrich-log-output.patch @@ -1,4 +1,4 @@ -From 425450509c8903d86b6f0c17acdbd52cb46c99fe Mon Sep 17 00:00:00 2001 +From 1dc077014395da0bba4bb05573c7a1f96f44c6a5 Mon Sep 17 00:00:00 2001 From: renoseven Date: Tue, 18 Feb 2025 17:50:34 +0800 Subject: [PATCH] upatch-manage: enrich log output @@ -336,5 +336,5 @@ index 8cc4867..474d857 100644 for (size_t i = 0; i < stack_size / sizeof(*stack); i++) { -- -2.34.1 +2.43.0 diff --git a/0018-project-change-build-options.patch b/0018-project-change-build-options.patch index f186c2a715cec7723ea8a953d4dfe63c08c415a4..b3e1871918da2631588333afac42fd32c3c815ff 100644 --- a/0018-project-change-build-options.patch +++ b/0018-project-change-build-options.patch @@ -1,4 +1,4 @@ -From 553e54f017d502da712c8d0e04bf8b40d634beac Mon Sep 17 00:00:00 2001 +From 6838a888ae87a78b9c0fc95edaee4ae1e93ce72a Mon Sep 17 00:00:00 2001 From: renoseven Date: Sat, 22 Feb 2025 17:38:12 +0800 Subject: [PATCH] project: change build options @@ -54,5 +54,5 @@ index ff219b9..37da26d 100644 message("-- Build flags: ${PROJECT_C_BUILD_FLAGS}") message("-- Link flags: ${PROJECT_C_LINK_FLAGS}") -- -2.34.1 +2.43.0 diff --git a/0019-upatch-manage-increase-jump-table-size-to-4096.patch b/0019-upatch-manage-increase-jump-table-size-to-4096.patch index 125e6842ebf58d1f1da729257c219468dd260645..10bc8efac4c15776617e211a957a271baa924ad7 100644 --- a/0019-upatch-manage-increase-jump-table-size-to-4096.patch +++ b/0019-upatch-manage-increase-jump-table-size-to-4096.patch @@ -1,4 +1,4 @@ -From c9b05a6f5cb8d55c6836a310542e133a0c0d1fb2 Mon Sep 17 00:00:00 2001 +From 2058c41ed76846943809a7b3f3d25c70e0b7a646 Mon Sep 17 00:00:00 2001 From: renoseven Date: Fri, 21 Feb 2025 14:37:37 +0800 Subject: [PATCH] upatch-manage: increase jump table size to 4096 @@ -22,5 +22,5 @@ index 2193f9a..6f62c7d 100644 #define UPATCH_HEADER_LEN 6 #define UPATCH_ID_LEN 40 -- -2.34.1 +2.43.0 diff --git a/0020-upatch-manage-fix-failed-to-attach-non-exist-process.patch b/0020-upatch-manage-fix-failed-to-attach-non-exist-process.patch index 2af16d82566b2bfc16826bbe5708877d1e397aef..2bcd4bd004b38e640d9f7119eb7b398141c453b1 100644 --- a/0020-upatch-manage-fix-failed-to-attach-non-exist-process.patch +++ b/0020-upatch-manage-fix-failed-to-attach-non-exist-process.patch @@ -1,4 +1,4 @@ -From 18a08f1f324974535bb00c7eed79f36fe5b8a4b7 Mon Sep 17 00:00:00 2001 +From c20f78f14932e89ee59b5c84feb03acf7bcdf0f6 Mon Sep 17 00:00:00 2001 From: renoseven Date: Fri, 21 Feb 2025 16:29:44 +0800 Subject: [PATCH] upatch-manage: fix 'failed to attach non-exist process' issue @@ -63,5 +63,5 @@ index 2d0845c..ab21891 100644 } while (1); -- -2.34.1 +2.43.0 diff --git a/0021-upatch-manage-fix-failed-to-alloc-patch-memory-issue.patch b/0021-upatch-manage-fix-failed-to-alloc-patch-memory-issue.patch index 734871e75fa8902135acef535a79d50f90998ffb..f6e8c3d284e91242dc2d50dea1fb87ad57579071 100644 --- a/0021-upatch-manage-fix-failed-to-alloc-patch-memory-issue.patch +++ b/0021-upatch-manage-fix-failed-to-alloc-patch-memory-issue.patch @@ -1,4 +1,4 @@ -From b41af7298a34f3f53d611f54aa1f93d1a8bc3e99 Mon Sep 17 00:00:00 2001 +From 175fd2d549806ae979bb64699d20ee55bcbf28a8 Mon Sep 17 00:00:00 2001 From: renoseven Date: Fri, 21 Feb 2025 15:15:31 +0800 Subject: [PATCH] upatch-manage: fix 'failed to alloc patch memory' issue @@ -522,5 +522,5 @@ index 23cbced..e8d5dee 100644 #endif -- -2.34.1 +2.43.0 diff --git a/0022-upatch-manage-fix-misresolve-.rela.plt-symbol-issue.patch b/0022-upatch-manage-fix-misresolve-.rela.plt-symbol-issue.patch index d1037ec9472a622e7df26388433a356a71407bfd..3b5e2406a50ad768d8f879bb2ce233fc1f23318b 100644 --- a/0022-upatch-manage-fix-misresolve-.rela.plt-symbol-issue.patch +++ b/0022-upatch-manage-fix-misresolve-.rela.plt-symbol-issue.patch @@ -1,4 +1,4 @@ -From b70bc8123941d7e7cf103c6c6731423297943935 Mon Sep 17 00:00:00 2001 +From 978eb28fe3cf5d13a404ce9fd51908513c62acdc Mon Sep 17 00:00:00 2001 From: renoseven Date: Fri, 21 Feb 2025 11:13:00 +0800 Subject: [PATCH] upatch-manage: fix 'misresolve .rela.plt symbol' issue @@ -25,5 +25,5 @@ index b564578..53debe6 100644 } -- -2.34.1 +2.43.0 diff --git a/0023-upatch-manage-fix-misresolve-std-cout-symbol-issue.patch b/0023-upatch-manage-fix-misresolve-std-cout-symbol-issue.patch index d8a6e2df0c556aa4675f29ea6b40797595ae365a..20b611172f7f5b9a7dcf8a39bf0000a32572d451 100644 --- a/0023-upatch-manage-fix-misresolve-std-cout-symbol-issue.patch +++ b/0023-upatch-manage-fix-misresolve-std-cout-symbol-issue.patch @@ -1,4 +1,4 @@ -From 13faaebfb43c8c374c14fdd049881c4558b497f0 Mon Sep 17 00:00:00 2001 +From c420f30ac116fd189fcc3c580046925c245902e5 Mon Sep 17 00:00:00 2001 From: renoseven Date: Fri, 21 Feb 2025 15:24:19 +0800 Subject: [PATCH] upatch-manage: fix 'misresolve std::cout symbol' issue @@ -25,5 +25,5 @@ index 5e0ddea..ed33925 100644 jmp_addr, tls_addr); -- -2.34.1 +2.43.0 diff --git a/0024-upatch-manage-fix-access-global-variable-coredump-is.patch b/0024-upatch-manage-fix-access-global-variable-coredump-is.patch index f6bdd4d92a5302c5d805b0284b513b2805644182..e58c3190631522b045fba6953c86152b1cb0ea22 100644 --- a/0024-upatch-manage-fix-access-global-variable-coredump-is.patch +++ b/0024-upatch-manage-fix-access-global-variable-coredump-is.patch @@ -1,4 +1,4 @@ -From daef225331b197ad5f047f36989f7eddeac63eec Mon Sep 17 00:00:00 2001 +From fea9b28ef8bfd4b54429023a05a9725ff8ef582e Mon Sep 17 00:00:00 2001 From: renoseven Date: Fri, 21 Feb 2025 14:34:09 +0800 Subject: [PATCH] upatch-manage: fix 'access global variable coredump' issue @@ -89,5 +89,5 @@ index 863bcc5..62efc13 100644 unsigned long, unsigned long); -- -2.34.1 +2.43.0 diff --git a/0025-project-update-CMakeLists.txt.patch b/0025-project-update-CMakeLists.txt.patch index a81c9405151015ea73368aa0f35c5d28ca374124..cff9fce2768a9729a47207f1506ca9f265195213 100644 --- a/0025-project-update-CMakeLists.txt.patch +++ b/0025-project-update-CMakeLists.txt.patch @@ -1,4 +1,4 @@ -From 63b964867143e5715e597e39a8209dec163e7de0 Mon Sep 17 00:00:00 2001 +From 43bc48384958e408f571e69c253e1d2c1d5b14c0 Mon Sep 17 00:00:00 2001 From: renoseven Date: Sat, 22 Feb 2025 18:24:36 +0800 Subject: [PATCH] project: update CMakeLists.txt @@ -32,5 +32,5 @@ index 37da26d..ca9fdfe 100644 message("-- Build flags: ${PROJECT_C_BUILD_FLAGS}") message("-- Link flags: ${PROJECT_C_LINK_FLAGS}") -- -2.34.1 +2.43.0 diff --git a/0026-upatch-manage-fix-compile-issue.patch b/0026-upatch-manage-fix-compile-issue.patch index 96a9cd143a41700ccdda938d34975b26518d2efd..014dee3d1afc801f958d6051993a50ebad8a070e 100644 --- a/0026-upatch-manage-fix-compile-issue.patch +++ b/0026-upatch-manage-fix-compile-issue.patch @@ -1,4 +1,4 @@ -From cd6381cf0634fb68b1f2b387adf3c559e8a923ba Mon Sep 17 00:00:00 2001 +From e20166661ed9e22fd64c5e20c840e672b8fc3a3e Mon Sep 17 00:00:00 2001 From: renoseven Date: Mon, 24 Feb 2025 10:07:17 +0800 Subject: [PATCH] upatch-manage: fix compile issue @@ -26,5 +26,5 @@ index 123ecfe..c3b07ac 100644 if (new_start > hole->start) { struct vm_hole *left = NULL; -- -2.34.1 +2.43.0 diff --git a/0027-syscare-build-supress-rpm-signature-warning.patch b/0027-syscare-build-supress-rpm-signature-warning.patch index d8d7b9058d176758d3e6e79056e88bf4db9f0359..346ae6825185b7336d3f31199aa25bbad7b2c1f5 100644 --- a/0027-syscare-build-supress-rpm-signature-warning.patch +++ b/0027-syscare-build-supress-rpm-signature-warning.patch @@ -1,4 +1,4 @@ -From 8a84b063e8e0d8261118cbe51b7dde68ffe0edf8 Mon Sep 17 00:00:00 2001 +From 7fe8dd23ff85c40074fb2e52d15523b9d653cd6d Mon Sep 17 00:00:00 2001 From: renoseven Date: Sat, 1 Mar 2025 14:47:37 +0800 Subject: [PATCH] syscare-build: supress rpm signature warning @@ -29,5 +29,5 @@ index 4054f67..ee7f19f 100644 .arg(pkg_path) .run_with_output()?; -- -2.34.1 +2.43.0 diff --git a/0028-syscare-build-support-custom-kernel-configuration.patch b/0028-syscare-build-support-custom-kernel-configuration.patch index 4570893d4c17ae0bd64d532b6eaa17a83b20551e..2b543dac79d72cfb8fa14b261dcdb8beeabd3418 100644 --- a/0028-syscare-build-support-custom-kernel-configuration.patch +++ b/0028-syscare-build-support-custom-kernel-configuration.patch @@ -1,4 +1,4 @@ -From 986c8ff3fcc4af577a90569dba5fe1585649c685 Mon Sep 17 00:00:00 2001 +From 3ce548a787062061335c9fc55f3b247e67ec25a2 Mon Sep 17 00:00:00 2001 From: renoseven Date: Fri, 28 Feb 2025 11:30:33 +0800 Subject: [PATCH] syscare-build: support custom kernel configuration @@ -204,5 +204,5 @@ index 8cbe9b3..f109b64 100644 fs::find_file( directory, -- -2.34.1 +2.43.0 diff --git a/0029-common-add-unit-test-for-process.patch b/0029-common-add-unit-test-for-process.patch index be0217b505f7d686ac6caae9fb0751605df5dff3..646e5b17f66093966930057f717b441e229de06a 100644 --- a/0029-common-add-unit-test-for-process.patch +++ b/0029-common-add-unit-test-for-process.patch @@ -1,4 +1,4 @@ -From 32df34f1fe208e9f99e58022f872ba68feeb14b8 Mon Sep 17 00:00:00 2001 +From b5343541223f1e41cec0c9406452965a09547036 Mon Sep 17 00:00:00 2001 From: xuxiaojuan1 Date: Tue, 7 May 2024 17:33:38 +0800 Subject: [PATCH] common: add unit test for process @@ -57,5 +57,5 @@ index d992372..4569587 100644 + } +} -- -2.34.1 +2.43.0 diff --git a/0030-syscare-build-add-unit-test-for-spec-writer.patch b/0030-syscare-build-add-unit-test-for-spec-writer.patch index 4e14b5980efbe29e33a10691d23beae8fc33624e..b644388be3db928080d61912898979431467d2fe 100644 --- a/0030-syscare-build-add-unit-test-for-spec-writer.patch +++ b/0030-syscare-build-add-unit-test-for-spec-writer.patch @@ -1,4 +1,4 @@ -From 001ddc89ebd935a556e0676d2aba244824570f03 Mon Sep 17 00:00:00 2001 +From 9bd4b7be1c266ffe51b526334588a75e0669fc50 Mon Sep 17 00:00:00 2001 From: xuxiaojuan1 Date: Wed, 8 May 2024 17:56:03 +0800 Subject: [PATCH] syscare-build: add unit test for spec writer @@ -46,5 +46,5 @@ index dc33459..97218c2 100644 + } +} -- -2.34.1 +2.43.0 diff --git a/0031-syscare-remove-root-permission-check.patch b/0031-syscare-remove-root-permission-check.patch index 11bb73c33d9dba11bc6abf12ef268edf8dc1db41..b5c4174c7ed4bb8057fc18d109a9863935fd7d32 100644 --- a/0031-syscare-remove-root-permission-check.patch +++ b/0031-syscare-remove-root-permission-check.patch @@ -1,4 +1,4 @@ -From b0d436bf14fc724a7820ebddda32da58114de8ff Mon Sep 17 00:00:00 2001 +From 87f0004364d811f74a444126052448bad1b8b49e Mon Sep 17 00:00:00 2001 From: renoseven Date: Wed, 12 Feb 2025 11:24:40 +0800 Subject: [PATCH] syscare: remove root permission check @@ -53,5 +53,5 @@ index 98e719d..b9606f0 100644 SubCommand::Info { identifiers } => { let mut patch_list = vec![]; -- -2.34.1 +2.43.0 diff --git a/0032-syscared-remove-upatch-failure-process-blacklist.patch b/0032-syscared-remove-upatch-failure-process-blacklist.patch index 28ab928f84727a6ebb5643a91659d5a981ebb649..fdbfd4fab39172af218796f8eed32c8ad4b5405c 100644 --- a/0032-syscared-remove-upatch-failure-process-blacklist.patch +++ b/0032-syscared-remove-upatch-failure-process-blacklist.patch @@ -1,4 +1,4 @@ -From fa19bb309e2cce60eba73a08408d228d9ef45a72 Mon Sep 17 00:00:00 2001 +From 025bbee900f0221ef318d10e9352579f3fdece0b Mon Sep 17 00:00:00 2001 From: renoseven Date: Wed, 12 Feb 2025 11:31:15 +0800 Subject: [PATCH] syscared: remove upatch failure process blacklist @@ -103,5 +103,5 @@ index 73ef94e..a1e9002 100644 if result.is_ok() { patch_entity.remove_process(pid) -- -2.34.1 +2.43.0 diff --git a/0033-syscare-optimize-syscare-info-syscare-target-output.patch b/0033-syscare-optimize-syscare-info-syscare-target-output.patch index 6579b2831e8c46bed6baa37bb47831f2c179ea3b..fbc6fa46db9cd1c63156e029e3993ea34d474882 100644 --- a/0033-syscare-optimize-syscare-info-syscare-target-output.patch +++ b/0033-syscare-optimize-syscare-info-syscare-target-output.patch @@ -1,4 +1,4 @@ -From 2d71a1c6c368392359869b3b641e2592db5bb859 Mon Sep 17 00:00:00 2001 +From a5e69b1d3c96c91b19aa7c99788991ef30cc0654 Mon Sep 17 00:00:00 2001 From: renoseven Date: Thu, 13 Feb 2025 09:40:23 +0800 Subject: [PATCH] syscare: optimize 'syscare info' & 'syscare target' output @@ -49,5 +49,5 @@ index b9606f0..5ad9cc2 100644 fn show_patch_status(status_list: impl IntoIterator) { -- -2.34.1 +2.43.0 diff --git a/0034-syscared-impl-syscare-rescan-command.patch b/0034-syscared-impl-syscare-rescan-command.patch index 73985ce731da4f51e9c8a5d0d984529cdfe8aea4..1ec86c8e25780f7b8980bdbf7f1c2815781c4db1 100644 --- a/0034-syscared-impl-syscare-rescan-command.patch +++ b/0034-syscared-impl-syscare-rescan-command.patch @@ -1,4 +1,4 @@ -From b0553998fe9b9947ead6d880d36b61721155bfbb Mon Sep 17 00:00:00 2001 +From eefbace91270aa2eea679df00fd626d4b3158b34 Mon Sep 17 00:00:00 2001 From: renoseven Date: Tue, 11 Feb 2025 17:29:13 +0800 Subject: [PATCH] syscared: impl 'syscare rescan' command @@ -40,5 +40,5 @@ index 8216428..38c9f37 100644 + } } -- -2.34.1 +2.43.0 diff --git a/0035-syscare-impl-syscare-rescan-command.patch b/0035-syscare-impl-syscare-rescan-command.patch index b09dda4a3e3ecacdd1a86acdccb44532849e141a..6829f6d53e44f7809245603e752c0516203837ba 100644 --- a/0035-syscare-impl-syscare-rescan-command.patch +++ b/0035-syscare-impl-syscare-rescan-command.patch @@ -1,4 +1,4 @@ -From 5636956c349b431b3467cfa993caf4469df37f8d Mon Sep 17 00:00:00 2001 +From 4960d37c168ebdf50ec6f1a402f375c0f9abf6e5 Mon Sep 17 00:00:00 2001 From: renoseven Date: Tue, 11 Feb 2025 17:38:41 +0800 Subject: [PATCH] syscare: impl 'syscare rescan' command @@ -55,5 +55,5 @@ index bb01a67..d328398 100644 + } } -- -2.34.1 +2.43.0 diff --git a/0036-syscared-impl-log-config.patch b/0036-syscared-impl-log-config.patch index 6e000433918a2a3c3f4f7e4292e9f586dfe77879..2b999d995ce0f67bfb32091ed89aa2cdab80e361 100644 --- a/0036-syscared-impl-log-config.patch +++ b/0036-syscared-impl-log-config.patch @@ -1,4 +1,4 @@ -From 90dfc6929f4e1bd170f034093bef8aea2b92ad89 Mon Sep 17 00:00:00 2001 +From 6777e5a3fb5fad1c5d5c14f0522c71e1876abb3f Mon Sep 17 00:00:00 2001 From: renoseven Date: Tue, 11 Feb 2025 18:10:38 +0800 Subject: [PATCH] syscared: impl log config @@ -137,5 +137,5 @@ index 42e9564..9ddfbe8 100644 fs::set_permissions( -- -2.34.1 +2.43.0 diff --git a/0037-syscared-impl-patch-blacklist.patch b/0037-syscared-impl-patch-blacklist.patch index e2d79cf5d7ba2cc298755cb383cebad5b81dc004..7b4094f457fee60632d2b044b36a0a2be344f0ce 100644 --- a/0037-syscared-impl-patch-blacklist.patch +++ b/0037-syscared-impl-patch-blacklist.patch @@ -1,4 +1,4 @@ -From f2c7cfcda4c6dbd09cbf5419a33d5dc646bc84d6 Mon Sep 17 00:00:00 2001 +From f1a905f95611481325b505412725d2e99ae14e9c Mon Sep 17 00:00:00 2001 From: renoseven Date: Wed, 12 Feb 2025 10:27:50 +0800 Subject: [PATCH] syscared: impl patch blacklist @@ -406,5 +406,5 @@ index 863f65b..4ec35f4 100644 patch_file, sys_file, -- -2.34.1 +2.43.0 diff --git a/0041-syscared-fix-patch-target-is-blocked-issue.patch b/0038-syscared-fix-patch-target-is-blocked-issue.patch similarity index 92% rename from 0041-syscared-fix-patch-target-is-blocked-issue.patch rename to 0038-syscared-fix-patch-target-is-blocked-issue.patch index ea4d93f30caad73ca9499e9194b4b8b075037f83..6d9eec8242f96579a7670e46e52a1ca53104e0c3 100644 --- a/0041-syscared-fix-patch-target-is-blocked-issue.patch +++ b/0038-syscared-fix-patch-target-is-blocked-issue.patch @@ -1,4 +1,4 @@ -From d8d7101dd519bbbd145c0735309bd0c3b5c7f253 Mon Sep 17 00:00:00 2001 +From 92dfc8490e548b0d6b687e39aa00d0185e874d84 Mon Sep 17 00:00:00 2001 From: renoseven Date: Mon, 3 Mar 2025 17:22:10 +0800 Subject: [PATCH] syscared: fix 'patch target is blocked' issue @@ -22,5 +22,5 @@ index 349d495..bdcdd4c 100644 patch.target_name.to_string_lossy(), ); -- -2.34.1 +2.43.0 diff --git a/0043-syscare-build-fix-detect-incorrect-kernel-source-dir.patch b/0039-syscare-build-fix-detect-incorrect-kernel-source-dir.patch similarity index 96% rename from 0043-syscare-build-fix-detect-incorrect-kernel-source-dir.patch rename to 0039-syscare-build-fix-detect-incorrect-kernel-source-dir.patch index 3d5bb4de31a56277669954dd9ec3eb68a7c175c5..3dc603d762eeee7ce7c9afeeca5f54cca3c236e9 100644 --- a/0043-syscare-build-fix-detect-incorrect-kernel-source-dir.patch +++ b/0039-syscare-build-fix-detect-incorrect-kernel-source-dir.patch @@ -1,4 +1,4 @@ -From 0d2a4fc0e9748a06c55d1962c5c794988f488338 Mon Sep 17 00:00:00 2001 +From 74500953bc32852cd53796306290c4508d123ec7 Mon Sep 17 00:00:00 2001 From: renoseven Date: Tue, 4 Mar 2025 11:32:31 +0800 Subject: [PATCH] syscare-build: fix 'detect incorrect kernel source directory' @@ -40,5 +40,5 @@ index accad0a..07d4a85 100644 let oot_source_dir = oot_module_entry.map(|build_entry| build_entry.build_source.clone()); -- -2.34.1 +2.43.0 diff --git a/0040-project-update-Cargo.lock.patch b/0040-project-update-Cargo.lock.patch deleted file mode 100644 index a3ea709a6caeb3d690fa77d554e830f273471d22..0000000000000000000000000000000000000000 --- a/0040-project-update-Cargo.lock.patch +++ /dev/null @@ -1,49 +0,0 @@ -From be50605c9b97f43af34e5bfdd284927514e9cdd4 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Thu, 13 Feb 2025 11:38:02 +0800 -Subject: [PATCH] project: update Cargo.lock - -Signed-off-by: renoseven ---- - Cargo.lock | 25 +++++++++++++++++++++++++ - 1 file changed, 25 insertions(+) - -diff --git a/Cargo.lock b/Cargo.lock -index 6ae9f36..ce0177e 100644 ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -679,6 +679,31 @@ dependencies = [ - "autocfg", - ] - -+[[package]] -+name = "metadata-generator" -+version = "1.2.2" -+dependencies = [ -+ "anyhow", -+ "clap", -+ "flexi_logger", -+ "lazy_static", -+ "log", -+ "syscare-abi", -+ "syscare-common", -+] -+ -+[[package]] -+name = "metadata-viewer" -+version = "1.2.2" -+dependencies = [ -+ "anyhow", -+ "clap", -+ "flexi_logger", -+ "log", -+ "syscare-abi", -+ "syscare-common", -+] -+ - [[package]] - name = "miniz_oxide" - version = "0.5.4" --- -2.34.1 - diff --git a/0044-upatch-manage-fix-compile-failure.patch b/0040-upatch-manage-fix-compile-failure.patch similarity index 91% rename from 0044-upatch-manage-fix-compile-failure.patch rename to 0040-upatch-manage-fix-compile-failure.patch index 0ac19b7ac920646b5b342cec483e1a1d99063a3e..7c9240b1f3f7f2378e4b28ea41b51355c968aa82 100644 --- a/0044-upatch-manage-fix-compile-failure.patch +++ b/0040-upatch-manage-fix-compile-failure.patch @@ -1,4 +1,4 @@ -From c8ee23919b11e0a0d3ed469af4213d692035d2f7 Mon Sep 17 00:00:00 2001 +From 689cb97db736a05d676f1a492910f6d96960cc5f Mon Sep 17 00:00:00 2001 From: renoseven Date: Wed, 5 Mar 2025 15:22:45 +0800 Subject: [PATCH] upatch-manage: fix compile failure @@ -22,5 +22,5 @@ index 80a817d..7dd82eb 100644 GElf_Rela *rel = (void *)shdrs[relsec].sh_addr; -- -2.34.1 +2.43.0 diff --git a/0045-syscared-fix-kmod-patch-conflicts-with-itself-issue.patch b/0041-syscared-fix-kmod-patch-conflicts-with-itself-issue.patch similarity index 97% rename from 0045-syscared-fix-kmod-patch-conflicts-with-itself-issue.patch rename to 0041-syscared-fix-kmod-patch-conflicts-with-itself-issue.patch index 00125ce9038cff2c4a296e03b129d18e0e1c77d9..6317ae8a674a50726be5565efe048dd899aa9666 100644 --- a/0045-syscared-fix-kmod-patch-conflicts-with-itself-issue.patch +++ b/0041-syscared-fix-kmod-patch-conflicts-with-itself-issue.patch @@ -1,4 +1,4 @@ -From 48fc62552f397d56c87f1d1879f5a88a9fee9835 Mon Sep 17 00:00:00 2001 +From 872947a5300e276f234944b44dcb169d3bf918a5 Mon Sep 17 00:00:00 2001 From: renoseven Date: Thu, 6 Mar 2025 10:37:17 +0800 Subject: [PATCH] syscared: fix 'kmod patch conflicts with itself' issue @@ -74,5 +74,5 @@ index beab803..49f1185 100644 .filter(|patch_function| !patch_function.is_same_function(uuid, function)) }) -- -2.34.1 +2.43.0 diff --git a/0046-common-fix-failed-to-acquire-flock-issue.patch b/0042-common-fix-failed-to-acquire-flock-issue.patch similarity index 98% rename from 0046-common-fix-failed-to-acquire-flock-issue.patch rename to 0042-common-fix-failed-to-acquire-flock-issue.patch index 0e2fccd887c6bfbe79f274242cb140b154d25429..99e061fe4dd4f6f0bb8995011f3b59a6a3a8a2d1 100644 --- a/0046-common-fix-failed-to-acquire-flock-issue.patch +++ b/0042-common-fix-failed-to-acquire-flock-issue.patch @@ -1,4 +1,4 @@ -From fef1fc6d7bc4a9e8805553a202ffde05ed570f23 Mon Sep 17 00:00:00 2001 +From 9234af9c63fee5f33f403b1aa5cffba1f6195c9e Mon Sep 17 00:00:00 2001 From: renoseven Date: Tue, 11 Mar 2025 12:01:48 +0800 Subject: [PATCH] common: fix 'failed to acquire flock' issue @@ -173,5 +173,5 @@ index bfd39d7..29bff55 100644 drop(shared_lock1); drop(shared_lock2); -- -2.34.1 +2.43.0 diff --git a/0047-syscare-rewrite-syscare-cli.patch b/0043-syscare-rewrite-syscare-cli.patch similarity index 99% rename from 0047-syscare-rewrite-syscare-cli.patch rename to 0043-syscare-rewrite-syscare-cli.patch index cae0376603781d422519ba658804a6c20d228cdf..d4f1713457507f56f2e4fc83bc1e7dac7c1b3a66 100644 --- a/0047-syscare-rewrite-syscare-cli.patch +++ b/0043-syscare-rewrite-syscare-cli.patch @@ -1,4 +1,4 @@ -From 2cebc4d7a83c1b7837b62ef5f9723a0b93ea18c4 Mon Sep 17 00:00:00 2001 +From 460621cf824ee7f38e7261ef43d3560d6c5e3c17 Mon Sep 17 00:00:00 2001 From: renoseven Date: Thu, 6 Mar 2025 16:48:10 +0800 Subject: [PATCH] syscare: rewrite syscare cli @@ -1348,5 +1348,5 @@ index f2c9244..0000000 - } -} -- -2.34.1 +2.43.0 diff --git a/0044-upatch-diff-fix-static-local-var-correlate.patch b/0044-upatch-diff-fix-static-local-var-correlate.patch new file mode 100644 index 0000000000000000000000000000000000000000..12f38e4ef65534823f06f77bbae551df440632c7 --- /dev/null +++ b/0044-upatch-diff-fix-static-local-var-correlate.patch @@ -0,0 +1,26 @@ +From 03b965c1147379eebad0547b618edb7e60949c87 Mon Sep 17 00:00:00 2001 +From: Jvle +Date: Thu, 27 Mar 2025 12:03:23 +0800 +Subject: [PATCH] upatch-diff: fix static local var correlate + +Signed-off-by: Jvle +--- + upatch-diff/elf-correlate.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/upatch-diff/elf-correlate.c b/upatch-diff/elf-correlate.c +index 979453b..35039b2 100644 +--- a/upatch-diff/elf-correlate.c ++++ b/upatch-diff/elf-correlate.c +@@ -432,7 +432,7 @@ void upatch_correlate_static_local_variables(struct upatch_elf *uelf_source, + if (bundled != patched_bundled) { + ERROR("bundle mismatch for symbol %s", sym->name); + } +- if (!bundled && sym->sec->twin != patched_sym->sec) { ++ if (!bundled && sym->sec->twin && sym->sec->twin != patched_sym->sec) { + ERROR("sections %s and %s aren't correlated for symbol %s", + sym->sec->name, patched_sym->sec->name, sym->name); + } +-- +2.43.0 + diff --git a/0045-upatch-manage-fix-first-object-cannot-find-mem-hole.patch b/0045-upatch-manage-fix-first-object-cannot-find-mem-hole.patch new file mode 100644 index 0000000000000000000000000000000000000000..635bc54bc37b309782dfda280e9c7ba5b1a83286 --- /dev/null +++ b/0045-upatch-manage-fix-first-object-cannot-find-mem-hole.patch @@ -0,0 +1,33 @@ +From 8f4374b1ae8a20f6c40ff355968b8e2d2f305bc2 Mon Sep 17 00:00:00 2001 +From: Jvle +Date: Wed, 26 Mar 2025 15:45:43 +0800 +Subject: [PATCH] upatch-manage: fix first object cannot find mem hole + +Signed-off-by: Jvle +--- + upatch-manage/upatch-process.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/upatch-manage/upatch-process.c b/upatch-manage/upatch-process.c +index c3b07ac..8e1882f 100644 +--- a/upatch-manage/upatch-process.c ++++ b/upatch-manage/upatch-process.c +@@ -889,7 +889,14 @@ struct vm_hole *find_patch_region(struct object_file *obj, size_t len) + struct obj_vm_area *vma = NULL; + list_for_each_entry(vma, &obj->vma, list) { + struct vm_hole *left_hole = obj->prev_hole; +- struct vm_hole *right_hole = next_hole(obj->prev_hole, vma_holes); ++ struct vm_hole *right_hole = NULL; ++ if (left_hole) { ++ right_hole = next_hole(left_hole, vma_holes); ++ } else { ++ if (!list_empty(vma_holes)) { ++ right_hole = list_first_entry(vma_holes, struct vm_hole, list); ++ } ++ } + + while ((left_hole != NULL) || (right_hole != NULL)) { + if (left_hole != NULL) { +-- +2.43.0 + diff --git a/0046-syscare-fix-request-is-unrecognized-issue.patch b/0046-syscare-fix-request-is-unrecognized-issue.patch new file mode 100644 index 0000000000000000000000000000000000000000..c675b27a9b56423a7e840fcdf670a5e8ce681f4b --- /dev/null +++ b/0046-syscare-fix-request-is-unrecognized-issue.patch @@ -0,0 +1,26 @@ +From da051ca015e9eec0e2108458fbb5af4d6f43a9b3 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Sat, 29 Mar 2025 17:43:59 +0800 +Subject: [PATCH] syscare: fix 'request is unrecognized' issue + +Signed-off-by: renoseven +--- + syscare/src/rpc/client.rs | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/syscare/src/rpc/client.rs b/syscare/src/rpc/client.rs +index c609849..3428984 100644 +--- a/syscare/src/rpc/client.rs ++++ b/syscare/src/rpc/client.rs +@@ -137,7 +137,7 @@ impl RpcClient { + match error { + jsonrpc::Error::Transport(err) => self.parse_transport_error(err), + jsonrpc::Error::Json(_) => anyhow!("Response format error"), +- jsonrpc::Error::Rpc(_) => anyhow!("Request is unrecognized"), ++ jsonrpc::Error::Rpc(e) => anyhow!(e.message), + _ => anyhow!("Unknown response error"), + } + } +-- +2.43.0 + diff --git a/0047-upatch-manage-fix-alloc-patch-memory-permission-deni.patch b/0047-upatch-manage-fix-alloc-patch-memory-permission-deni.patch new file mode 100644 index 0000000000000000000000000000000000000000..f5203463635f0bddab63409fffc4ff4b20d59218 --- /dev/null +++ b/0047-upatch-manage-fix-alloc-patch-memory-permission-deni.patch @@ -0,0 +1,28 @@ +From 4686876bff5f70a2287e174c2bedb308b8e107cf Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Tue, 1 Apr 2025 18:41:37 +0800 +Subject: [PATCH] upatch-manage: fix 'alloc patch memory permission denied' + issue + +Signed-off-by: renoseven +--- + upatch-manage/upatch-patch.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/upatch-manage/upatch-patch.c b/upatch-manage/upatch-patch.c +index 4a1e568..4b1b1be 100644 +--- a/upatch-manage/upatch-patch.c ++++ b/upatch-manage/upatch-patch.c +@@ -278,8 +278,7 @@ static void *upatch_alloc(struct object_file *obj, size_t len) + log_debug("Found patch region at 0x%lx, size=0x%lx\n", addr, len); + + addr = upatch_mmap_remote(pctx, addr, len, +- PROT_READ | PROT_WRITE | PROT_EXEC, +- MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, ++ PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, + (unsigned long)-1, 0); + if (addr == 0) { + log_error("Failed to map patch region, ret=%d\n", errno); +-- +2.43.0 + diff --git a/0048-upatch-diff-remove-line-macro-related-functions.patch b/0048-upatch-diff-remove-line-macro-related-functions.patch new file mode 100644 index 0000000000000000000000000000000000000000..e9690c19fbd82d8e24c698145233629e60870a5e --- /dev/null +++ b/0048-upatch-diff-remove-line-macro-related-functions.patch @@ -0,0 +1,239 @@ +From e8fc9b5b01a4e7df5d8dd6689c3d99f0844a71ab Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Tue, 1 Apr 2025 18:51:57 +0800 +Subject: [PATCH] upatch-diff: remove line macro related functions + +Signed-off-by: renoseven +--- + upatch-diff/elf-compare.c | 208 -------------------------------------- + 1 file changed, 208 deletions(-) + +diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c +index 7ca6845..fe97528 100644 +--- a/upatch-diff/elf-compare.c ++++ b/upatch-diff/elf-compare.c +@@ -166,208 +166,6 @@ out: + return 0; + } + +-bool upatch_handle_redis_line(const char *symname) +-{ +- if (!strncmp(symname, "_serverPanic", 12) || +- !strncmp(symname, "_serverAssert", 13) || +- !strncmp(symname, "_serverAssertWithInfo", 21) || +- !strncmp(symname, "rdbReportError", 14) || +- !strncmp(symname, "RedisModule__Assert", 19)) { +- return true; +- } +- +- return false; +-} +- +-/* TODO: let user support this list or generate by the compiler ? */ +-bool check_line_func(const char *symname) +-{ +- if (!strncmp(basename(g_relf_name), "redis-server", 12)) { +- return upatch_handle_redis_line(symname); +- } +- +- return false; +-} +- +-/* Determine if a section has changed only due to a __LINE__ bumber change. +- * For example, a WARN() or might_sleep() macro's embedding of the line number into an +- * instruction operand. +- */ +-static bool line_macro_change_only_x86_64(struct upatch_elf *uelf, +- struct section *sec) +-{ +- unsigned long offset; +- unsigned long insn1_len; +- unsigned long insn2_len; +- +- void *data1; +- void *data2; +- void *insn1; +- void *insn2; +- +- struct rela *rela = NULL; +- bool found_any = false; +- bool found = false; +- +- if (sec->status != CHANGED || +- is_rela_section(sec) || +- !is_text_section(sec) || +- sec->sh.sh_size != sec->twin->sh.sh_size || +- !sec->rela || +- sec->rela->status != SAME) { +- return false; +- } +- +- data1 = sec->twin->data->d_buf; +- data2 = sec->data->d_buf; +- for (offset = 0; offset < sec->sh.sh_size; offset += insn1_len) { +- insn1 = data1 + offset; +- insn2 = data2 + offset; +- +- insn1_len = insn_length(uelf, insn1); +- insn2_len = insn_length(uelf, insn2); +- if (!insn1_len || !insn2_len) { +- ERROR("decode instruction in section %s at offset 0x%lx failed", +- sec->name, offset); +- } +- +- if (insn1_len != insn2_len) { +- return false; +- } +- +- /* if insn are same, continue */ +- if (!memcmp(insn1, insn2, insn1_len)) { +- continue; +- } +- log_debug("check list for %s at 0x%lx\n", sec->name, offset); +- +- /* +- * Here we found a differece between two instructions of the +- * same length. Only ignore the change if: +- * +- * 1) the instruction match a known pattern of a '__LINE__' +- * macro immediate value which was embedded in the instruction. +- * +- * 2) the instructions are followed by certain expected relocations. +- * (white-list) +- */ +- if (!insn_is_load_immediate(uelf, insn1) || +- !insn_is_load_immediate(uelf, insn2)) { +- return false; +- } +- +- found = false; +- list_for_each_entry(rela, &sec->rela->relas, list) { +- if (rela->offset < offset + insn1_len) { +- continue; +- } +- if (rela->string) { +- continue; +- } +- /* TODO: we may need black list ? */ +- if (check_line_func(rela->sym->name)) { +- found = true; +- break; +- } +- return false; +- } +- if (!found) { +- return false; +- } +- +- found_any = true; +- } +- +- if (!found_any) { +- ERROR("no instruction changes detected for changed section %s", +- sec->name); +- } +- +- return true; +-} +- +-static bool line_macro_change_only_aarch64(struct upatch_elf *uelf, +- struct section *sec) +-{ +- unsigned long start1; +- unsigned long start2; +- unsigned long size; +- unsigned long offset; +- +- struct rela *rela = NULL; +- bool found_any = false; +- bool found = false; +- +- unsigned int mov_imm_mask = ((1<<16) - 1)<<5; +- unsigned long insn_len = insn_length(uelf, NULL); +- +- if (sec->status != CHANGED || +- is_rela_section(sec) || +- !is_text_section(sec) || +- sec->sh.sh_size != sec->twin->sh.sh_size || +- !sec->rela || +- sec->rela->status != SAME) { +- return false; +- } +- +- start1 = (unsigned long)sec->twin->data->d_buf; +- start2 = (unsigned long)sec->data->d_buf; +- size = sec->sh.sh_size; +- for (offset = 0; offset < size; offset += insn_len) { +- if (!memcmp((void *)start1 + offset, (void *)start2 + offset, +- insn_len)) { +- continue; +- } +- +- /* verify it's a mov immediate to w1 */ +- if ((*(unsigned int *)(start1 + offset) & ~mov_imm_mask) != +- (*(unsigned int *)(start2 + offset) & ~mov_imm_mask)) { +- return false; +- } +- +- found = false; +- list_for_each_entry(rela, &sec->rela->relas, list) { +- if (rela->offset < offset + insn_len) { +- continue; +- } +- if (rela->string) { +- continue; +- } +- /* TODO: we may need black list ? */ +- if (check_line_func(rela->sym->name)) { +- found = true; +- break; +- } +- return false; +- } +- if (!found) { +- return false; +- } +- +- found_any = true; +- } +- +- if (!found_any) { +- ERROR("no instruction changes detected for changed section %s", +- sec->name); +- } +- +- return true; +-} +- +-static bool line_macro_change_only(struct upatch_elf *uelf, struct section *sec) +-{ +- switch (uelf->arch) { +- case AARCH64: +- return line_macro_change_only_aarch64(uelf, sec); +- case X86_64: +- return line_macro_change_only_x86_64(uelf, sec); +- default: +- ERROR("unsupported arch"); +- } +- return false; +-} +- + static void update_section_status(struct section *sec, enum status status) + { + if (sec == NULL) { +@@ -397,12 +195,6 @@ void upatch_compare_sections(struct upatch_elf *uelf) + } else { + compare_correlated_section(sec, sec->twin); + } +- /* exclude WARN-only, might_sleep changes */ +- if (line_macro_change_only(uelf, sec)) { +- log_debug("reverting line number section %s status to SAME\n", +- sec->name); +- sec->status = SAME; +- } + /* sync status */ + update_section_status(sec, sec->status); + update_section_status(sec->twin, sec->status); +-- +2.43.0 + diff --git a/0049-upatch-build-support-override-line-macros.patch b/0049-upatch-build-support-override-line-macros.patch new file mode 100644 index 0000000000000000000000000000000000000000..58f8078ed6861ba97d1bf4d3c055d9d5e2fe172f --- /dev/null +++ b/0049-upatch-build-support-override-line-macros.patch @@ -0,0 +1,113 @@ +From e217de3518df8b292409524ded68f4a8c8736081 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 31 Mar 2025 10:12:49 +0800 +Subject: [PATCH] upatch-build: support override line macros + +1. add "--keep-line-macros" argument +2. replace all "__LINE__" macros in source files to "0" + +Signed-off-by: renoseven +--- + upatch-build/src/args.rs | 4 ++++ + upatch-build/src/main.rs | 14 ++++++++++++++ + upatch-build/src/project.rs | 23 +++++++++++++++++++++-- + 3 files changed, 39 insertions(+), 2 deletions(-) + +diff --git a/upatch-build/src/args.rs b/upatch-build/src/args.rs +index 7462856..cb9bbef 100644 +--- a/upatch-build/src/args.rs ++++ b/upatch-build/src/args.rs +@@ -90,6 +90,10 @@ pub struct Arguments { + #[clap(short, long, default_value = DEFAULT_OUTPUT_DIR)] + pub output_dir: PathBuf, + ++ /// Keep line macro unchanged ++ #[clap(long)] ++ pub keep_line_macros: bool, ++ + /// Skip compiler version check (not recommended) + #[clap(long)] + pub skip_compiler_check: bool, +diff --git a/upatch-build/src/main.rs b/upatch-build/src/main.rs +index 09f907b..51956d8 100644 +--- a/upatch-build/src/main.rs ++++ b/upatch-build/src/main.rs +@@ -281,6 +281,13 @@ impl UpatchBuild { + .prepare() + .with_context(|| format!("Failed to prepare {}", project))?; + ++ if !self.args.keep_line_macros { ++ info!("Overriding line macros"); ++ project ++ .override_line_macros() ++ .context("Failed to override line macros")?; ++ } ++ + info!("Building '{}'", project); + project + .build() +@@ -300,6 +307,13 @@ impl UpatchBuild { + .apply_patches() + .with_context(|| format!("Failed to patch {}", project))?; + ++ if !self.args.keep_line_macros { ++ info!("Overriding line macros"); ++ project ++ .override_line_macros() ++ .context("Failed to override line macros")?; ++ } ++ + info!("Building '{}'", project); + project + .build() +diff --git a/upatch-build/src/project.rs b/upatch-build/src/project.rs +index 0caa0a2..636d00f 100644 +--- a/upatch-build/src/project.rs ++++ b/upatch-build/src/project.rs +@@ -17,7 +17,7 @@ use std::{ + ffi::{OsStr, OsString}, + fs::File, + io::Write, +- os::unix::ffi::OsStrExt, ++ os::unix::ffi::{OsStrExt as _, OsStringExt}, + path::{Path, PathBuf}, + }; + +@@ -27,7 +27,7 @@ use log::{debug, Level}; + use which::which; + + use crate::{args::Arguments, build_root::BuildRoot, compiler::CompilerInfo, dwarf::ProducerType}; +-use syscare_common::{concat_os, fs, process::Command}; ++use syscare_common::{concat_os, ffi::OsStrExt, fs, process::Command}; + + const PATCH_BIN: &str = "patch"; + const UPATCH_HELPER_BIN: &str = "upatch-helper"; +@@ -175,6 +175,25 @@ impl Project<'_> { + Ok(()) + } + ++ pub fn override_line_macros(&self) -> Result<()> { ++ const LINE_MACRO_NAME: &str = "__LINE__"; ++ const LINE_MACRO_VALUE: &str = "0"; ++ ++ let file_list = fs::list_files(self.source_dir, fs::TraverseOptions { recursive: true })?; ++ for file_path in file_list { ++ let old_contents = fs::read(&file_path)?; ++ let new_contents = OsStr::from_bytes(&old_contents) ++ .replace(LINE_MACRO_NAME, LINE_MACRO_VALUE) ++ .into_vec(); ++ if old_contents != new_contents { ++ debug!("* {}", file_path.display()); ++ fs::write(&file_path, new_contents)?; ++ } ++ } ++ ++ Ok(()) ++ } ++ + pub fn prepare(&self) -> Result<()> { + self.exec_command(PREPARE_SCRIPT_NAME, self.prepare_cmd) + } +-- +2.43.0 + diff --git a/0050-syscare-build-add-keep-line-macros-argument.patch b/0050-syscare-build-add-keep-line-macros-argument.patch new file mode 100644 index 0000000000000000000000000000000000000000..9f0d388275e3413ba606e99944b5f1cf8b6a7ccd --- /dev/null +++ b/0050-syscare-build-add-keep-line-macros-argument.patch @@ -0,0 +1,85 @@ +From 831ebfc34ef12e84fb0dcd27d1dc1f876b2a3090 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 31 Mar 2025 16:19:26 +0800 +Subject: [PATCH] syscare-build: add '--keep-line-macros' argument + +Signed-off-by: renoseven +--- + syscare-build/src/args.rs | 4 ++++ + syscare-build/src/build_params.rs | 1 + + syscare-build/src/main.rs | 1 + + syscare-build/src/patch/user_patch/upatch_builder.rs | 5 +++++ + 4 files changed, 11 insertions(+) + +diff --git a/syscare-build/src/args.rs b/syscare-build/src/args.rs +index a90b77a..4a51715 100644 +--- a/syscare-build/src/args.rs ++++ b/syscare-build/src/args.rs +@@ -97,6 +97,10 @@ pub struct Arguments { + #[clap(short, long, default_value = &DEFAULT_BUILD_JOBS)] + pub jobs: usize, + ++ /// Keep line macro unchanged (userspace patch only) ++ #[clap(long)] ++ pub keep_line_macros: bool, ++ + /// Skip compiler version check (not recommended) + #[clap(long)] + pub skip_compiler_check: bool, +diff --git a/syscare-build/src/build_params.rs b/syscare-build/src/build_params.rs +index f0e391c..29dd960 100644 +--- a/syscare-build/src/build_params.rs ++++ b/syscare-build/src/build_params.rs +@@ -39,6 +39,7 @@ pub struct BuildParameters { + pub patch_description: String, + pub patch_files: Vec, + pub jobs: usize, ++ pub keep_line_macros: bool, + pub skip_compiler_check: bool, + pub skip_cleanup: bool, + pub verbose: bool, +diff --git a/syscare-build/src/main.rs b/syscare-build/src/main.rs +index dec67b2..51f9050 100644 +--- a/syscare-build/src/main.rs ++++ b/syscare-build/src/main.rs +@@ -305,6 +305,7 @@ impl SyscareBuild { + patch_type, + patch_files, + jobs: self.args.jobs, ++ keep_line_macros: self.args.keep_line_macros, + skip_compiler_check: self.args.skip_compiler_check, + skip_cleanup: self.args.skip_cleanup, + verbose: self.args.verbose, +diff --git a/syscare-build/src/patch/user_patch/upatch_builder.rs b/syscare-build/src/patch/user_patch/upatch_builder.rs +index 9165380..a69373c 100644 +--- a/syscare-build/src/patch/user_patch/upatch_builder.rs ++++ b/syscare-build/src/patch/user_patch/upatch_builder.rs +@@ -54,6 +54,7 @@ struct UBuildParameters { + patch_target: PackageInfo, + patch_description: String, + patch_files: Vec, ++ keep_line_macros: bool, + skip_compiler_check: bool, + verbose: bool, + } +@@ -181,6 +182,7 @@ impl UserPatchBuilder { + patch_target: build_params.build_entry.target_pkg.to_owned(), + patch_description: build_params.patch_description.to_owned(), + patch_files: build_params.patch_files.to_owned(), ++ keep_line_macros: build_params.keep_line_macros, + skip_compiler_check: build_params.skip_compiler_check, + verbose: build_params.verbose, + }; +@@ -223,6 +225,9 @@ impl UserPatchBuilder { + .arg("--output-dir") + .arg(&ubuild_params.patch_output_dir); + ++ if ubuild_params.keep_line_macros { ++ cmd_args.arg("--keep-line-macros"); ++ } + if ubuild_params.skip_compiler_check { + cmd_args.arg("--skip-compiler-check"); + } +-- +2.43.0 + diff --git a/0051-common-fs-glob-wildcard-path-includes-current-direct.patch b/0051-common-fs-glob-wildcard-path-includes-current-direct.patch new file mode 100644 index 0000000000000000000000000000000000000000..befd5a30b952d28762b40d5c39af5f657661dce3 --- /dev/null +++ b/0051-common-fs-glob-wildcard-path-includes-current-direct.patch @@ -0,0 +1,25 @@ +From b5cc04bed8d3bd87bf507990af3f2ef10413d6eb Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 3 Apr 2025 15:47:44 +0800 +Subject: [PATCH] common: fs::glob wildcard path includes current directory + +Signed-off-by: renoseven +--- + syscare-common/src/fs/fs_impl.rs | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/syscare-common/src/fs/fs_impl.rs b/syscare-common/src/fs/fs_impl.rs +index 30c11b7..58f97c3 100644 +--- a/syscare-common/src/fs/fs_impl.rs ++++ b/syscare-common/src/fs/fs_impl.rs +@@ -620,6 +620,7 @@ pub fn glob>(path: P) -> io::Result> { + if let Component::Normal(pattern) = components[comp_idx] { + if pattern == WILDCARD_RECURSIVE { + if let Ok(read_dir) = self::read_dir(&curr_dir) { ++ stack.push((curr_dir.clone(), comp_idx + 1)); + for dir_entry in read_dir.flatten() { + let next_path = dir_entry.path(); + if next_path.is_dir() { +-- +2.43.0 + diff --git a/0052-upatch-build-only-replace-line-macros-for-source-fil.patch b/0052-upatch-build-only-replace-line-macros-for-source-fil.patch new file mode 100644 index 0000000000000000000000000000000000000000..61429442930b2213f4e8e1e519695c20877af7bd --- /dev/null +++ b/0052-upatch-build-only-replace-line-macros-for-source-fil.patch @@ -0,0 +1,72 @@ +From e8f8c432b08dcdfdfcb93fc6d131929145052ce2 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 11 Apr 2025 15:30:36 +0800 +Subject: [PATCH] upatch-build: only replace line macros for source files + +1. add '--source-ext' argument +2. check extension whitelist before replacing '__LINE__' macros + +Signed-off-by: renoseven +--- + upatch-build/src/args.rs | 5 +++++ + upatch-build/src/project.rs | 7 +++++++ + 2 files changed, 12 insertions(+) + +diff --git a/upatch-build/src/args.rs b/upatch-build/src/args.rs +index cb9bbef..5871f82 100644 +--- a/upatch-build/src/args.rs ++++ b/upatch-build/src/args.rs +@@ -23,6 +23,7 @@ use which::which; + use super::{CLI_ABOUT, CLI_NAME, CLI_VERSION}; + + const DEFAULT_EMPTY_VALUE: &str = ""; ++const DEFAULT_SOURCE_EXT: [&str; 8] = ["h", "hpp", "hxx", "c", "cpp", "cxx", "in", "inc"]; + const DEFAULT_COMPILERS: [&str; 2] = ["gcc", "g++"]; + const DEFAULT_BUILD_ROOT: &str = "."; + const DEFAULT_OUTPUT_DIR: &str = "."; +@@ -50,6 +51,10 @@ pub struct Arguments { + #[clap(short, long)] + pub source_dir: PathBuf, + ++ /// Source file extension(s) ++ #[clap(long, multiple = true, default_values = &DEFAULT_SOURCE_EXT)] ++ pub source_ext: Vec, ++ + /// Build compiler(s) + #[clap(long, multiple = true, default_values = &DEFAULT_COMPILERS)] + pub compiler: Vec, +diff --git a/upatch-build/src/project.rs b/upatch-build/src/project.rs +index 636d00f..d563c02 100644 +--- a/upatch-build/src/project.rs ++++ b/upatch-build/src/project.rs +@@ -49,6 +49,7 @@ pub struct Project<'a> { + name: OsString, + build_root: &'a BuildRoot, + source_dir: &'a Path, ++ source_ext: &'a [OsString], + prepare_cmd: &'a OsStr, + build_cmd: &'a OsStr, + clean_cmd: &'a OsStr, +@@ -92,6 +93,7 @@ impl<'a> Project<'a> { + .to_os_string(), + build_root, + source_dir: args.source_dir.as_path(), ++ source_ext: args.source_ext.as_slice(), + prepare_cmd: args.prepare_cmd.as_os_str(), + build_cmd: args.build_cmd.as_os_str(), + clean_cmd: args.clean_cmd.as_os_str(), +@@ -181,6 +183,11 @@ impl Project<'_> { + + let file_list = fs::list_files(self.source_dir, fs::TraverseOptions { recursive: true })?; + for file_path in file_list { ++ let file_ext = file_path.extension().unwrap_or_default(); ++ if self.source_ext.iter().all(|ext| ext != file_ext) { ++ continue; ++ } ++ + let old_contents = fs::read(&file_path)?; + let new_contents = OsStr::from_bytes(&old_contents) + .replace(LINE_MACRO_NAME, LINE_MACRO_VALUE) +-- +2.43.0 + diff --git a/0053-upatch-manage-container_of-use-void-instead-of-char.patch b/0053-upatch-manage-container_of-use-void-instead-of-char.patch new file mode 100644 index 0000000000000000000000000000000000000000..83b4bf584f609c8bad52ce921f0ef39fa50fa12c --- /dev/null +++ b/0053-upatch-manage-container_of-use-void-instead-of-char.patch @@ -0,0 +1,26 @@ +From 4e8f082c4c5552fea89da476b43c55303fdf18f0 Mon Sep 17 00:00:00 2001 +From: Jvle +Date: Wed, 23 Apr 2025 16:52:11 +0800 +Subject: [PATCH] upatch-manage: container_of: use void* instead of char* + +Signed-off-by: Jvle +--- + upatch-manage/list.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/upatch-manage/list.h b/upatch-manage/list.h +index f175c29..9e55a75 100644 +--- a/upatch-manage/list.h ++++ b/upatch-manage/list.h +@@ -34,7 +34,7 @@ + */ + + #define container_of(ptr, type, member) \ +- ((type *)(((char *)(ptr)) - offsetof(type, member))) ++ ((type *)(((void *)(ptr)) - offsetof(type, member))) + + struct list_head { + struct list_head *next, *prev; +-- +2.43.0 + diff --git a/0054-CMake-move-EXECUTE_PROCESS-from-upatch-manage-to-top.patch b/0054-CMake-move-EXECUTE_PROCESS-from-upatch-manage-to-top.patch new file mode 100644 index 0000000000000000000000000000000000000000..d2bb84a895f64d1a43beb57231c604395218691b --- /dev/null +++ b/0054-CMake-move-EXECUTE_PROCESS-from-upatch-manage-to-top.patch @@ -0,0 +1,46 @@ +From 5b4ea24bb263e667c48a96be261244e0021e2dee Mon Sep 17 00:00:00 2001 +From: Jvle +Date: Wed, 23 Apr 2025 17:00:17 +0800 +Subject: [PATCH] CMake: move EXECUTE_PROCESS from upatch-manage to top CMake + file + +Signed-off-by: Jvle +--- + CMakeLists.txt | 5 +++++ + upatch-manage/CMakeLists.txt | 4 ---- + 2 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index ca9fdfe..d8f3258 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -4,6 +4,11 @@ cmake_minimum_required(VERSION 3.14) + + project(syscare) + ++# Arch ++EXECUTE_PROCESS(COMMAND uname -m ++ OUTPUT_VARIABLE ARCH ++ OUTPUT_STRIP_TRAILING_WHITESPACE) ++ + # Includes + include(GNUInstallDirs) + find_package(Git QUIET) +diff --git a/upatch-manage/CMakeLists.txt b/upatch-manage/CMakeLists.txt +index e09aa9c..1f7ecd0 100644 +--- a/upatch-manage/CMakeLists.txt ++++ b/upatch-manage/CMakeLists.txt +@@ -2,10 +2,6 @@ + + set(UPATCH_MANAGE "upatch-manage") + +-EXECUTE_PROCESS(COMMAND uname -m +- OUTPUT_VARIABLE ARCH +- OUTPUT_STRIP_TRAILING_WHITESPACE) +- + set(ARCH_PATH arch/${ARCH}) + + include_directories( +-- +2.43.0 + diff --git a/0055-upatch-diff-impl-section-type-checking.patch b/0055-upatch-diff-impl-section-type-checking.patch new file mode 100644 index 0000000000000000000000000000000000000000..a2a91c132a2e5a613af48d337a7aa319f781fdcf --- /dev/null +++ b/0055-upatch-diff-impl-section-type-checking.patch @@ -0,0 +1,127 @@ +From 8a872ea234403dcee20b0f7af4db54b8fc3a1699 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 25 Apr 2025 10:12:09 +0800 +Subject: [PATCH] upatch-diff: impl section type checking + +Signed-off-by: renoseven +--- + upatch-diff/elf-common.h | 78 +++++++++++++++++++++++++++++----------- + 1 file changed, 57 insertions(+), 21 deletions(-) + +diff --git a/upatch-diff/elf-common.h b/upatch-diff/elf-common.h +index bc2c1ac..5e63b09 100644 +--- a/upatch-diff/elf-common.h ++++ b/upatch-diff/elf-common.h +@@ -49,31 +49,40 @@ + } \ + } while (0) + +-static inline bool is_rela_section(struct section *sec) ++static inline bool is_text_section(struct section *sec) + { +- /* +- * An architecture usually only accepts one type. +- * And, X86_64 only uses RELA +- */ +- return (sec->sh.sh_type == SHT_RELA); ++ return (sec != NULL) && ++ (sec->sh.sh_type == SHT_PROGBITS) && ++ (sec->sh.sh_flags & SHF_EXECINSTR); + } + ++static inline bool is_data_section(struct section *sec) ++{ ++ return (sec != NULL) && ++ (sec->sh.sh_type == SHT_PROGBITS) && ++ (sec->sh.sh_flags & SHF_WRITE); ++} + +-static inline bool is_text_section(struct section *sec) ++static inline bool is_rodata_section(struct section *sec) + { +- return (sec->sh.sh_type == SHT_PROGBITS && +- (sec->sh.sh_flags & SHF_EXECINSTR)); ++ return (sec != NULL) && ++ (sec->sh.sh_type == SHT_PROGBITS) && ++ ((sec->sh.sh_flags & SHF_WRITE) == 0); + } + +-static inline bool is_string_section(struct section *sec) ++static inline bool is_symtab_section(struct section *sec) + { +- return sec->sh.sh_flags & SHF_STRINGS; ++ return (sec != NULL) && (sec->sh.sh_type == SHT_SYMTAB); + } + +-/* used for c++ exception handle */ +-static inline bool is_except_section(struct section *sec) ++static inline bool is_strtab_section(struct section *sec) + { +- return !strncmp(sec->name, ".gcc_except_table", 17); ++ return (sec != NULL) && (sec->sh.sh_type == SHT_STRTAB); ++} ++ ++static inline bool is_rela_section(struct section *sec) ++{ ++ return (sec != NULL) && (sec->sh.sh_type == SHT_RELA); + } + + static inline bool is_note_section(struct section *sec) +@@ -81,7 +90,40 @@ static inline bool is_note_section(struct section *sec) + if (is_rela_section(sec)) { + sec = sec->base; + } +- return sec->sh.sh_type == SHT_NOTE; ++ return (sec->sh.sh_type == SHT_NOTE); ++} ++ ++static inline bool is_bss_section(struct section *sec) ++{ ++ return (sec != NULL) && (sec->sh.sh_type == SHT_NOBITS); ++} ++ ++static inline bool is_group_section(struct section *sec) ++{ ++ return (sec != NULL) && (sec->sh.sh_type == SHT_GROUP); ++} ++ ++static inline bool is_read_only_section(struct section *sec) ++{ ++ return (sec != NULL) && ((sec->sh.sh_flags & SHF_WRITE) == 0); ++} ++ ++static inline bool is_string_section(struct section *sec) ++{ ++ return (sec != NULL) && (sec->sh.sh_flags & SHF_STRINGS); ++} ++ ++static inline bool is_string_literal_section(struct section *sec) ++{ ++ return (sec != NULL) && ++ (sec->sh.sh_flags & SHF_STRINGS) && ++ ((sec->sh.sh_flags & SHF_WRITE) == 0); ++} ++ ++/* used for c++ exception handle */ ++static inline bool is_except_section(struct section *sec) ++{ ++ return !strncmp(sec->name, ".gcc_except_table", 17); + } + + static inline bool is_eh_frame(struct section *sec) +@@ -160,12 +202,6 @@ static inline struct section *find_section_by_name(struct list_head *list, const + return NULL; + } + +-// section like .rodata.str1. and .rodata.__func__. +-static inline bool is_string_literal_section(struct section *sec) +-{ +- return !strncmp(sec->name, ".rodata.", 8) && (strstr(sec->name, ".str") || strstr(sec->name, "__func__")); +-} +- + static inline bool has_digit_tail(char *tail) + { + if (*tail != '.') { +-- +2.43.0 + diff --git a/0056-upatch-diff-allow-string-literal-section-being-inclu.patch b/0056-upatch-diff-allow-string-literal-section-being-inclu.patch new file mode 100644 index 0000000000000000000000000000000000000000..f93a161e2befc015544e4862570033b9fce922af --- /dev/null +++ b/0056-upatch-diff-allow-string-literal-section-being-inclu.patch @@ -0,0 +1,81 @@ +From 8c5cdf3bde909616963f441decd189fedcb6b374 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 25 Apr 2025 15:45:38 +0800 +Subject: [PATCH] upatch-diff: allow string literal section being included + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 53 +++++++++++++++++--------------- + 1 file changed, 29 insertions(+), 24 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 1c14b7a..c792f16 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -910,34 +910,39 @@ static bool has_tls_included(struct upatch_elf *uelf) + + static void verify_patchability(struct upatch_elf *uelf) + { +- struct section *sec; ++ struct section *sec = NULL; ++ struct rela *rela = NULL; + int errs = 0; + + list_for_each_entry(sec, &uelf->sections, list) { +- if (sec->status == CHANGED && !sec->include && !is_rela_section(sec)) { +- log_normal("Section '%s' changed, but not included\n", sec->name); +- errs++; +- } +- +- if (sec->status != SAME && sec->grouped) { +- log_normal("Section '%s' is changed, but it is in section group\n", +- sec->name); +- errs++; +- } +- +- if (sec->sh.sh_type == SHT_GROUP && sec->status == NEW) { +- log_normal("Section '%s' is new, but it is not supported\n", +- sec->name); +- errs++; ++ if (sec->status != SAME) { // NEW or CHANGED ++ if ((sec->include == 0) && !is_rela_section(sec)) { ++ log_warn("Section '%s' is changed, but it is not included\n", ++ sec->name); ++ errs++; ++ } ++ if ((sec->grouped != 0) || is_group_section(sec)) { ++ log_warn("Section '%s' is changed, but it is in a group\n", ++ sec->name); ++ errs++; ++ } + } +- +- if ((sec->include && sec->status != NEW) && +- (!strncmp(sec->name, ".data", 5) || +- !strncmp(sec->name, ".bss", 4)) && +- (strcmp(sec->name, ".data.unlikely") && +- strcmp(sec->name, ".data.once"))) { +- log_normal("Data section '%s' is included", sec->name); +- errs++; ++ if (sec->status != NEW) { // SAME or CHANGED ++ if (sec->rela == NULL) { ++ continue; ++ } ++ if (!is_data_section(sec) && !is_bss_section(sec)) { ++ continue; ++ } ++ list_for_each_entry(rela, &sec->rela->relas, list) { ++ if ((rela->sym == NULL) || (rela->sym->status == NEW)) { ++ continue; ++ } ++ if (!is_string_literal_section(rela->sym->sec)) { ++ log_warn("Data section '%s' is changed\n", sec->name); ++ errs++; ++ } ++ } + } + } + +-- +2.43.0 + diff --git a/0057-upatch-diff-fix-code-logic-when-drop-rela.patch b/0057-upatch-diff-fix-code-logic-when-drop-rela.patch new file mode 100644 index 0000000000000000000000000000000000000000..edc5bff629e77fcac332f3f37fefcba42a2985a4 --- /dev/null +++ b/0057-upatch-diff-fix-code-logic-when-drop-rela.patch @@ -0,0 +1,30 @@ +From 3d90b7d23c8f02792d0df6a8296cc6ecf1b714fe Mon Sep 17 00:00:00 2001 +From: Jvle +Date: Wed, 23 Apr 2025 16:55:26 +0800 +Subject: [PATCH] upatch-diff: fix code logic when drop rela + +Signed-off-by: Jvle +--- + upatch-diff/create-diff-object.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index c792f16..8a4089d 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -978,8 +978,10 @@ static void migrate_included_elements(struct upatch_elf *uelf_patched, + list_add_tail(&sec->list, &uelf_out->sections); + sec->index = 0; + +- if (!is_rela_section(sec) && sec->secsym && !sec->secsym->include) { +- sec->secsym = NULL; // break link to non-included section symbol ++ if (!is_rela_section(sec)) { ++ if (sec->secsym && !sec->secsym->include) { ++ sec->secsym = NULL; // break link to non-included section symbol ++ } + } + } + +-- +2.43.0 + diff --git a/0058-upatch-diff-fix-cannot-detect-some-changes-issue.patch b/0058-upatch-diff-fix-cannot-detect-some-changes-issue.patch new file mode 100644 index 0000000000000000000000000000000000000000..e1756fec63ae3758ed7e29892efd527ecd710269 --- /dev/null +++ b/0058-upatch-diff-fix-cannot-detect-some-changes-issue.patch @@ -0,0 +1,112 @@ +From 24e2572e478ac32fb0bb908b11b9bf6bcfe07bb5 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 25 Apr 2025 18:06:32 +0800 +Subject: [PATCH] upatch-diff: fix cannot detect some changes issue + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 53 ++++++++++++++++---------------- + 1 file changed, 26 insertions(+), 27 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 8a4089d..731bbdb 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -763,24 +763,24 @@ static void include_symbol(struct symbol *sym) + + static void include_section(struct section *sec) + { +- struct rela *rela; ++ struct rela *rela = NULL; + +- if (sec->include) { ++ if (sec->include != 0) { + return; + } + + sec->include = 1; +- if (sec->secsym) { +- sec->secsym->include = 1; +- } + +- if (!sec->rela) { +- return; +- } +- +- sec->rela->include = 1; +- list_for_each_entry(rela, &sec->rela->relas, list) { +- include_symbol(rela->sym); ++ if (!is_rela_section(sec)) { ++ if (sec->secsym != NULL) { ++ sec->secsym->include = 1; ++ } ++ if (sec->rela != NULL) { ++ sec->rela->include = 1; ++ list_for_each_entry(rela, &sec->rela->relas, list) { ++ include_symbol(rela->sym); ++ } ++ } + } + } + +@@ -808,27 +808,26 @@ static void include_standard_elements(struct upatch_elf *uelf) + list_entry(uelf->symbols.next, struct symbol, list)->include = 1; + } + +-static int include_changed_functions(struct upatch_elf *uelf) ++static int include_changes(struct upatch_elf *uelf) + { + struct symbol *sym; + int changed_nr = 0; + + list_for_each_entry(sym, &uelf->symbols, list) { +- if (sym->status == CHANGED && +- sym->type == STT_FUNC) { +- changed_nr++; +- include_symbol(sym); ++ if (sym->status != CHANGED) { ++ continue; + } +- /* exception handler is a special function */ +- if (sym->status == CHANGED && +- sym->type == STT_SECTION && +- sym->sec && is_except_section(sym->sec)) { +- log_warn("Exception section '%s' is changed\n", sym->sec->name); ++ ++ if (sym->type == STT_FUNC) { + changed_nr++; + include_symbol(sym); +- } +- if (sym->type == STT_FILE) { +- sym->include = 1; ++ } else if (sym->type == STT_SECTION) { ++ if (is_string_literal_section(sym->sec) || is_except_section(sym->sec)) { ++ changed_nr++; ++ include_symbol(sym); ++ } ++ } else if (sym->type == STT_FILE) { ++ include_symbol(sym); + } + } + +@@ -935,7 +934,7 @@ static void verify_patchability(struct upatch_elf *uelf) + continue; + } + list_for_each_entry(rela, &sec->rela->relas, list) { +- if ((rela->sym == NULL) || (rela->sym->status == NEW)) { ++ if ((rela->sym == NULL) || (rela->sym->status != CHANGED)) { + continue; + } + if (!is_string_literal_section(rela->sym->sec)) { +@@ -1064,7 +1063,7 @@ int main(int argc, char*argv[]) + + include_standard_elements(&uelf_patched); + +- num_changed = include_changed_functions(&uelf_patched); ++ num_changed = include_changes(&uelf_patched); + new_globals_exist = include_new_globals(&uelf_patched); + if (!num_changed && !new_globals_exist) { + log_normal("No functional changes\n"); +-- +2.43.0 + diff --git a/0059-upatch-diff-fix-.text-section-change-does-not-includ.patch b/0059-upatch-diff-fix-.text-section-change-does-not-includ.patch new file mode 100644 index 0000000000000000000000000000000000000000..fce488727914afc45d076364099726bb838f1ab6 --- /dev/null +++ b/0059-upatch-diff-fix-.text-section-change-does-not-includ.patch @@ -0,0 +1,66 @@ +From 66edfa93f7587ddd20166516f6d8e827030b0318 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 25 Apr 2025 10:25:11 +0800 +Subject: [PATCH] upatch-diff: fix .text section change does not include symbol + issue + +Signed-off-by: renoseven +--- + upatch-diff/elf-compare.c | 37 +++++++++++++++++++++++-------------- + 1 file changed, 23 insertions(+), 14 deletions(-) + +diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c +index fe97528..6443544 100644 +--- a/upatch-diff/elf-compare.c ++++ b/upatch-diff/elf-compare.c +@@ -29,24 +29,33 @@ + #include "elf-compare.h" + #include "elf-insn.h" + +-static void compare_correlated_symbol(struct symbol *sym, +- struct symbol *symtwin) ++static int compare_correlated_section(struct section *sec, struct section *twin); ++ ++static void compare_correlated_symbol(struct symbol *sym, struct symbol *twin) + { +- // compare bind and type info +- if (sym->sym.st_info != symtwin->sym.st_info || +- (sym->sec && !symtwin->sec) || +- (symtwin->sec && !sym->sec)) { +- ERROR("symbol info mismatch: %s", sym->name); ++ // symbol type & binding cannot be changed ++ if (sym->type != twin->type) { ++ ERROR("symbol '%s' type mismatched", sym->name); + } +- // check if correlated symbols have correlated sections +- if (sym->sec && symtwin->sec && sym->sec->twin != symtwin->sec) { +- ERROR("symbol changed sections: %s", sym->name); ++ if (sym->sym.st_info != twin->sym.st_info) { ++ ERROR("symbol '%s' binding mismatched", sym->name); + } +- // data object can't change size +- if (sym->type == STT_OBJECT && sym->sym.st_size != symtwin->sym.st_size) { +- ERROR("object size mismatch: %s", sym->name); ++ // object symbol size cannot be changed ++ if ((sym->type == STT_OBJECT) && (sym->sym.st_size != twin->sym.st_size)) { ++ ERROR("symbol '%s' object size mismatched", sym->name); + } +- if (sym->sym.st_shndx == SHN_UNDEF || sym->sym.st_shndx == SHN_ABS) { ++ ++ // compare symbol sections ++ if ((sym->sec != NULL) && (twin->sec != NULL)) { ++ // symbol section correlation cannot be changed ++ if (sym->sec->twin != twin->sec) { ++ ERROR("symbol '%s' section mismatched", sym->name); ++ } ++ compare_correlated_section(sym->sec, twin->sec); ++ sym->status = sym->sec->status; ++ } ++ ++ if ((sym->sym.st_shndx == SHN_UNDEF) || (sym->sym.st_shndx == SHN_ABS)) { + sym->status = SAME; + } + /* +-- +2.43.0 + diff --git a/0060-upatch-diff-fix-.data.rel-section-is-changed-issue.patch b/0060-upatch-diff-fix-.data.rel-section-is-changed-issue.patch new file mode 100644 index 0000000000000000000000000000000000000000..8560f85c0b3bed6d64dcf83473611d3e3d2b2877 --- /dev/null +++ b/0060-upatch-diff-fix-.data.rel-section-is-changed-issue.patch @@ -0,0 +1,33 @@ +From a25609c99493b219a43afa8146ba5ebdf00744eb Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 25 Apr 2025 18:13:55 +0800 +Subject: [PATCH] upatch-diff: fix .data.rel section is changed issue + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 731bbdb..a5bc1ab 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -937,10 +937,12 @@ static void verify_patchability(struct upatch_elf *uelf) + if ((rela->sym == NULL) || (rela->sym->status != CHANGED)) { + continue; + } +- if (!is_string_literal_section(rela->sym->sec)) { +- log_warn("Data section '%s' is changed\n", sec->name); +- errs++; ++ if (is_read_only_section(sec) || ++ is_string_literal_section(rela->sym->sec)) { ++ continue; + } ++ log_warn("Data section '%s' is changed\n", sec->name); ++ errs++; + } + } + } +-- +2.43.0 + diff --git a/0061-upatch-diff-rewrite-patch-verification-logic.patch b/0061-upatch-diff-rewrite-patch-verification-logic.patch new file mode 100644 index 0000000000000000000000000000000000000000..c6f39a1643c958c913a35bdd386a4ea0617b1f61 --- /dev/null +++ b/0061-upatch-diff-rewrite-patch-verification-logic.patch @@ -0,0 +1,144 @@ +From 9d90dc4bc5b36ab2f3578f6888c874bcbb9123ff Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 25 Apr 2025 10:14:54 +0800 +Subject: [PATCH] upatch-diff: rewrite patch verification logic + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 102 +++++++++++++++++++------------ + 1 file changed, 62 insertions(+), 40 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index a5bc1ab..980c111 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -894,64 +894,86 @@ static void include_debug_sections(struct upatch_elf *uelf) + /* currently, there si no special section need to be handled */ + static void process_special_sections(void) {} + +-static bool has_tls_included(struct upatch_elf *uelf) ++static int verify_symbol_patchability(struct upatch_elf *uelf) + { +- struct symbol *sym; ++ int err_count = 0; + ++ struct symbol *sym = NULL; + list_for_each_entry(sym, &uelf->symbols, list) { +- if (sym->include == 1 && sym->type == STT_TLS) { +- log_normal("TLS symbol '%s' is not supported", sym->name); +- return true; ++ if (sym->include == 0) { ++ continue; ++ } ++ if (sym->type == STT_TLS) { ++ log_warn("Symbol '%s' is included, but TLS is not supported\n", ++ sym->name); ++ err_count++; ++ } ++ if (sym->type == STT_GNU_IFUNC) { ++ log_warn("Symbol '%s' is included, but IFUNC is not supported\n", ++ sym->name); ++ err_count++; + } + } +- return false; ++ ++ return err_count; + } + +-static void verify_patchability(struct upatch_elf *uelf) ++static int verify_section_patchability(struct upatch_elf *uelf) + { +- struct section *sec = NULL; +- struct rela *rela = NULL; +- int errs = 0; ++ int err_count = 0; + ++ struct section *sec = NULL; + list_for_each_entry(sec, &uelf->sections, list) { +- if (sec->status != SAME) { // NEW or CHANGED +- if ((sec->include == 0) && !is_rela_section(sec)) { +- log_warn("Section '%s' is changed, but it is not included\n", +- sec->name); +- errs++; +- } +- if ((sec->grouped != 0) || is_group_section(sec)) { +- log_warn("Section '%s' is changed, but it is in a group\n", +- sec->name); +- errs++; +- } +- } +- if (sec->status != NEW) { // SAME or CHANGED +- if (sec->rela == NULL) { ++ if ((sec->status == NEW) && (sec->include == 0)) { ++ // new sections should be included ++ log_warn("Section '%s' is %s, but it is not included\n", ++ sec->name, status_str(sec->status)); ++ err_count++; ++ } else if ((sec->status == CHANGED) && (sec->include == 0)) { ++ // changed sections should be included, except rela & debug section ++ if (is_rela_section(sec) || is_debug_section(sec)) { + continue; + } +- if (!is_data_section(sec) && !is_bss_section(sec)) { +- continue; ++ log_warn("Section '%s' is %s, but it is not included\n", ++ sec->name, status_str(sec->status)); ++ err_count++; ++ } else if ((sec->status == CHANGED) && (sec->include != 0)) { ++ // changed group section cannot be included ++ if (is_group_section(sec) || (sec->grouped != 0)) { ++ log_warn("Section '%s' is %s, but it is not supported\n", ++ sec->name, status_str(sec->status)); ++ err_count++; + } +- list_for_each_entry(rela, &sec->rela->relas, list) { +- if ((rela->sym == NULL) || (rela->sym->status != CHANGED)) { +- continue; +- } +- if (is_read_only_section(sec) || +- is_string_literal_section(rela->sym->sec)) { +- continue; ++ // changed .data & .bss section cannot be included ++ if (is_data_section(sec) || is_bss_section(sec)) { ++ struct rela *rela = NULL; ++ list_for_each_entry(rela, &sec->rela->relas, list) { ++ if ((rela->sym == NULL) || (rela->sym->status != CHANGED)) { ++ continue; ++ } ++ if (is_read_only_section(rela->sym->sec) || ++ is_string_literal_section(rela->sym->sec)) { ++ continue; ++ } ++ log_warn("Section '%s' is %s, but it is not supported\n", ++ sec->name, status_str(sec->status)); ++ err_count++; + } +- log_warn("Data section '%s' is changed\n", sec->name); +- errs++; + } + } + } + +- if (errs) { +- ERROR("%d, Unsupported section changes", errs); +- } +- if (has_tls_included(uelf)) { +- ERROR("Unsupported symbol included"); ++ return err_count; ++} ++ ++static void verify_patchability(struct upatch_elf *uelf) ++{ ++ int err_count = 0; ++ ++ err_count += verify_symbol_patchability(uelf); ++ err_count += verify_section_patchability(uelf); ++ if (err_count != 0) { ++ ERROR("Found %d unexpected changes", err_count); + } + } + +-- +2.43.0 + diff --git a/0062-upatch-diff-rewrite-symbol-include-logic.patch b/0062-upatch-diff-rewrite-symbol-include-logic.patch new file mode 100644 index 0000000000000000000000000000000000000000..fd73e60a57d998c48c69cb3aac9be987495b0f05 --- /dev/null +++ b/0062-upatch-diff-rewrite-symbol-include-logic.patch @@ -0,0 +1,370 @@ +From f0204e122efa867de74b7db5573958fe5ff2919a Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 28 Apr 2025 11:37:46 +0800 +Subject: [PATCH] upatch-diff: rewrite symbol include logic + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 142 ++++++++----------------------- + upatch-diff/elf-debug.c | 107 ----------------------- + upatch-diff/elf-debug.h | 2 - + 3 files changed, 34 insertions(+), 217 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 980c111..9c3bc7e 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -739,7 +739,7 @@ static void include_special_local_section(struct upatch_elf *uelf) { + static void include_section(struct section *sec); + static void include_symbol(struct symbol *sym) + { +- if (sym->include) { ++ if ((sym == NULL) || (sym->include != 0)) { + return; + } + /* +@@ -747,6 +747,8 @@ static void include_symbol(struct symbol *sym) + * might be needed: either permanently for a rela, or temporarily for + * the later creation of a dynrela. + */ ++ log_debug("Include symbol '%s', status: %s\n", ++ sym->name, status_str(sym->status)); + sym->include = 1; + /* + * For a function/object symbol, if it has a section, we only need to +@@ -756,144 +758,76 @@ static void include_symbol(struct symbol *sym) + * For section symbols, we always include the section because + * references to them can't otherwise be resolved externally. + */ +- if (sym->sec && (sym->type == STT_SECTION || sym->status != SAME)) { ++ if ((sym->status != SAME) || (sym->type == STT_SECTION)) { + include_section(sym->sec); + } + } + + static void include_section(struct section *sec) + { +- struct rela *rela = NULL; +- +- if (sec->include != 0) { ++ if ((sec == NULL) || (sec->include != 0)) { + return; + } + ++ log_debug("Include section '%s', status: %s\n", ++ sec->name, status_str(sec->status)); + sec->include = 1; + +- if (!is_rela_section(sec)) { +- if (sec->secsym != NULL) { +- sec->secsym->include = 1; +- } +- if (sec->rela != NULL) { +- sec->rela->include = 1; +- list_for_each_entry(rela, &sec->rela->relas, list) { +- include_symbol(rela->sym); +- } ++ if (is_rela_section(sec)) { ++ struct rela *rela = NULL; ++ list_for_each_entry(rela, &sec->relas, list) { ++ include_symbol(rela->sym); + } ++ return; ++ } else { ++ include_symbol(sec->secsym); ++ include_section(sec->rela); + } + } + + static void include_standard_elements(struct upatch_elf *uelf) + { +- struct section *sec; +- struct symbol *sym; ++ struct section *sec = NULL; + + list_for_each_entry(sec, &uelf->sections, list) { +- if (!strcmp(sec->name, ".shstrtab") || +- !strcmp(sec->name, ".strtab") || +- !strcmp(sec->name, ".symtab") || +- !strcmp(sec->name, ".rodata") || +- is_string_literal_section(sec)) { ++ if (is_symtab_section(sec) || is_strtab_section(sec)) { + include_section(sec); + } + } +- +- list_for_each_entry(sym, &uelf->symbols, list) { +- if (sym->sec && is_string_literal_section(sym->sec)) { +- sym->include = 1; +- } +- } + /* include the NULL symbol */ +- list_entry(uelf->symbols.next, struct symbol, list)->include = 1; ++ include_symbol(list_entry(uelf->symbols.next, struct symbol, list)); + } + + static int include_changes(struct upatch_elf *uelf) + { +- struct symbol *sym; +- int changed_nr = 0; ++ int count = 0; + ++ struct symbol *sym = NULL; + list_for_each_entry(sym, &uelf->symbols, list) { +- if (sym->status != CHANGED) { ++ if (sym->status == SAME) { + continue; + } + +- if (sym->type == STT_FUNC) { +- changed_nr++; ++ if ((sym->type == STT_OBJECT) || ++ (sym->type == STT_FUNC) || ++ (sym->type == STT_COMMON) || ++ (sym->type == STT_TLS) || ++ (sym->type == STT_GNU_IFUNC)) { + include_symbol(sym); ++ count++; + } else if (sym->type == STT_SECTION) { +- if (is_string_literal_section(sym->sec) || is_except_section(sym->sec)) { +- changed_nr++; +- include_symbol(sym); ++ if ((sym->sec != NULL) && ++ (is_rela_section(sym->sec) || is_debug_section(sym->sec))) { ++ continue; + } +- } else if (sym->type == STT_FILE) { +- include_symbol(sym); +- } +- } +- +- return changed_nr; +-} +- +-static int include_new_globals(struct upatch_elf *uelf) +-{ +- struct symbol *sym; +- int nr = 0; +- +- list_for_each_entry(sym, &uelf->symbols, list) { +- if (sym->bind == STB_GLOBAL && sym->sec && sym->status == NEW) { + include_symbol(sym); +- nr++; ++ count++; + } + } + +- return nr; ++ return count; + } + +-static void include_debug_sections(struct upatch_elf *uelf) +-{ +- struct rela *rela; +- struct rela *saferela; +- struct section *sec = NULL; +- struct section *eh_sec = NULL; +- +- /* include all .debug_* sections */ +- list_for_each_entry(sec, &uelf->sections, list) { +- if (is_debug_section(sec)) { +- sec->include = 1; +- if (!is_rela_section(sec) && sec->secsym) { +- sec->secsym->include = 1; +- } +- if (!is_rela_section(sec) && is_eh_frame(sec)) { +- eh_sec = sec; +- } +- } +- } +- +- /* +- * modify relocation entry here +- * remove unincluded symbol in debug relocation section +- * for eh_frame section, sync the FDE at the same time +- */ +- list_for_each_entry(sec, &uelf->sections, list) { +- if (!is_rela_section(sec) || !is_debug_section(sec)) { +- continue; +- } +- list_for_each_entry_safe(rela, saferela, &sec->relas, list) { +- // The shndex of symbol is SHN_COMMON, there is no related section +- if (rela->sym && !rela->sym->include) { +- list_del(&rela->list); +- free(rela); +- } +- } +- } +- if (eh_sec) { +- upatch_rebuild_eh_frame(eh_sec); +- } +-} +- +-/* currently, there si no special section need to be handled */ +-static void process_special_sections(void) {} +- + static int verify_symbol_patchability(struct upatch_elf *uelf) + { + int err_count = 0; +@@ -1033,9 +967,6 @@ int main(int argc, char*argv[]) + struct upatch_elf uelf_out; + struct running_elf relf; + +- int num_changed; +- int new_globals_exist; +- + memset(&arguments, 0, sizeof(arguments)); + argp_parse(&argp, argc, argv, 0, NULL, &arguments); + +@@ -1087,9 +1018,8 @@ int main(int argc, char*argv[]) + + include_standard_elements(&uelf_patched); + +- num_changed = include_changes(&uelf_patched); +- new_globals_exist = include_new_globals(&uelf_patched); +- if (!num_changed && !new_globals_exist) { ++ int change_count = include_changes(&uelf_patched); ++ if (change_count == 0) { + log_normal("No functional changes\n"); + upatch_elf_destroy(&uelf_source); + upatch_elf_destroy(&uelf_patched); +@@ -1101,10 +1031,6 @@ int main(int argc, char*argv[]) + return 0; + } + +- include_debug_sections(&uelf_patched); +- +- process_special_sections(); +- + upatch_print_changes(&uelf_patched); + + upatch_dump_kelf(&uelf_patched); +diff --git a/upatch-diff/elf-debug.c b/upatch-diff/elf-debug.c +index 9d2641a..983bf03 100644 +--- a/upatch-diff/elf-debug.c ++++ b/upatch-diff/elf-debug.c +@@ -160,110 +160,3 @@ static inline bool skip_bytes(unsigned char **iter, unsigned char *end, + *iter += len; + return true; + } +- +-void upatch_rebuild_eh_frame(struct section *sec) +-{ +- void *eh_frame; +- unsigned long long frame_size; +- +- struct rela *rela; +- unsigned char *data; +- unsigned char *data_end; +- +- unsigned int hdr_length; +- unsigned int hdr_id; +- +- unsigned long current_offset; +- unsigned int count = 0; +- +- /* sanity check */ +- if (!is_eh_frame(sec) || is_rela_section(sec) || !sec->rela) { +- return; +- } +- +- list_for_each_entry(rela, &sec->rela->relas, list) { +- count++; +- } +- +- /* currently, only delete is possible */ +- if (sec->rela->sh.sh_entsize != 0 && +- count == sec->rela->sh.sh_size / sec->rela->sh.sh_entsize) { +- return; +- } +- +- log_debug("sync modification for eh_frame\n"); +- data = sec->data->d_buf; +- data_end = sec->data->d_buf + sec->data->d_size; +- +- /* in this time, some relcation entries may have been deleted */ +- frame_size = 0; +- eh_frame = calloc(1, sec->data->d_size); +- if (!eh_frame) { +- ERROR("malloc eh_frame failed\n"); +- } +- +- /* 8 is the offset of PC begin */ +- current_offset = 8; +- list_for_each_entry(rela, &sec->rela->relas, list) { +- unsigned long offset = rela->offset; +- bool found_rela = false; +- log_debug("handle relocaton offset at 0x%lx\n", offset); +- while (data != data_end) { +- void *__src = data; +- +- log_debug("current handle offset is 0x%lx\n", current_offset); +- +- REQUIRE(skip_bytes(&data, data_end, 4), "no length to be read"); +- hdr_length = *(unsigned int *)(data - 4); +- +- REQUIRE(hdr_length != 0xffffffff, +- "64 bit .eh_frame is not supported"); +- /* if it is 0, we reach the end. */ +- if (hdr_length == 0) { +- break; +- } +- +- REQUIRE(skip_bytes(&data, data_end, 4), "no length to be read"); +- hdr_id = *(unsigned int *)(data - 4); +- +- REQUIRE(skip_bytes(&data, data_end, hdr_length - 4), +- "no length to be read"); +- if (current_offset == offset) { +- found_rela = true; +- } +- +- /* CIE or relocation releated FDE */ +- if (hdr_id == 0 || found_rela) { +- memcpy(eh_frame + frame_size, __src, hdr_length + 4); +- /* update rela offset to point to new offset, and also hdr_id */ +- if (found_rela) { +- /* 4 is the offset of hdr_id and 8 is the offset of PC begin */ +- *(unsigned long *)(eh_frame + frame_size + 4) = frame_size + 4; +- rela->offset = frame_size + 8; +- } +- +- frame_size += (hdr_length + 4); +- } else { +- log_debug("remove FDE at 0x%lx\n", current_offset); +- } +- /* hdr_length(value) + hdr_length(body) */ +- current_offset += (4 + hdr_length); +- +- if (found_rela) { +- break; +- } +- } +- } +- +- /* +- * FIXME: data may not reach the data_end, since we have found +- * all FDE for relocation entries, the only problem here is +- * we may miss the CIE, but CIE is always in the beginning ? +- */ +- +- sec->data->d_buf = eh_frame; +- sec->data->d_size = frame_size; +- sec->dbuf_source = DATA_SOURCE_ALLOC; +- +- sec->sh.sh_size = frame_size; +-} +diff --git a/upatch-diff/elf-debug.h b/upatch-diff/elf-debug.h +index 0852c94..7c8db40 100644 +--- a/upatch-diff/elf-debug.h ++++ b/upatch-diff/elf-debug.h +@@ -31,6 +31,4 @@ void upatch_print_changes(struct upatch_elf *); + + void upatch_dump_kelf(struct upatch_elf *); + +-void upatch_rebuild_eh_frame(struct section *); +- + #endif /* __UPATCH_ELF_DEBUG_H_ */ +-- +2.43.0 + diff --git a/0063-upatch-diff-allow-.rodata-section-sh_addralign-chang.patch b/0063-upatch-diff-allow-.rodata-section-sh_addralign-chang.patch new file mode 100644 index 0000000000000000000000000000000000000000..9ee6d81fef8d82af428cc292904889dd56942c69 --- /dev/null +++ b/0063-upatch-diff-allow-.rodata-section-sh_addralign-chang.patch @@ -0,0 +1,48 @@ +From 260ceee3a124b9f569b73b265cf46fbff6837f10 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 28 Apr 2025 11:50:33 +0800 +Subject: [PATCH] upatch-diff: allow .rodata section sh_addralign changes + +Signed-off-by: renoseven +--- + upatch-diff/elf-compare.c | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c +index 6443544..c31dbb9 100644 +--- a/upatch-diff/elf-compare.c ++++ b/upatch-diff/elf-compare.c +@@ -131,17 +131,20 @@ static void compare_correlated_nonrela_section(struct section *sec, + static int compare_correlated_section(struct section *sec, + struct section *sectwin) + { +- /* TODO: addr align of rodata has changed. after strlen(str) >= 30, align 8 exists */ + /* compare section headers */ +- if (sec->sh.sh_type != sectwin->sh.sh_type || +- sec->sh.sh_flags != sectwin->sh.sh_flags || +- sec->sh.sh_entsize != sectwin->sh.sh_entsize || +- (sec->sh.sh_addralign != sectwin->sh.sh_addralign && +- !is_text_section(sec) && !is_string_section(sec))) { +- ERROR("%s section header details differ from %s", +- sec->name, sectwin->name); +- return -1; +- } ++ if ((sec->sh.sh_type != sectwin->sh.sh_type) || ++ (sec->sh.sh_flags != sectwin->sh.sh_flags) || ++ (sec->sh.sh_entsize != sectwin->sh.sh_entsize) || ++ ((sec->sh.sh_addralign != sectwin->sh.sh_addralign) && ++ !is_text_section(sec) && ++ !is_string_section(sec) && ++ !is_rodata_section(sec))) { ++ /* shaddralign of .rodata may be changed from 0 to 8 bytes ++ once string length is over 30 */ ++ ERROR("%s section header details differ from %s", ++ sec->name, sectwin->name); ++ return -1; ++ } + + if (is_note_section(sec)) { + sec->status = SAME; +-- +2.43.0 + diff --git a/0064-upatch-diff-allow-.debug_-section-header-changes.patch b/0064-upatch-diff-allow-.debug_-section-header-changes.patch new file mode 100644 index 0000000000000000000000000000000000000000..55d3a87c54e3330f8a566e4ef39b5e1cc7a4a7c5 --- /dev/null +++ b/0064-upatch-diff-allow-.debug_-section-header-changes.patch @@ -0,0 +1,50 @@ +From 7e95a981545700bf4f16fed70d8a00c6e410dd40 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 28 Apr 2025 12:16:26 +0800 +Subject: [PATCH] upatch-diff: allow .debug_ section header changes + +Signed-off-by: renoseven +--- + upatch-diff/elf-compare.c | 26 ++++++++++++++------------ + 1 file changed, 14 insertions(+), 12 deletions(-) + +diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c +index c31dbb9..56451af 100644 +--- a/upatch-diff/elf-compare.c ++++ b/upatch-diff/elf-compare.c +@@ -132,18 +132,20 @@ static int compare_correlated_section(struct section *sec, + struct section *sectwin) + { + /* compare section headers */ +- if ((sec->sh.sh_type != sectwin->sh.sh_type) || +- (sec->sh.sh_flags != sectwin->sh.sh_flags) || +- (sec->sh.sh_entsize != sectwin->sh.sh_entsize) || +- ((sec->sh.sh_addralign != sectwin->sh.sh_addralign) && +- !is_text_section(sec) && +- !is_string_section(sec) && +- !is_rodata_section(sec))) { +- /* shaddralign of .rodata may be changed from 0 to 8 bytes +- once string length is over 30 */ +- ERROR("%s section header details differ from %s", +- sec->name, sectwin->name); +- return -1; ++ if (!is_debug_section(sec)) { ++ if ((sec->sh.sh_type != sectwin->sh.sh_type) || ++ (sec->sh.sh_flags != sectwin->sh.sh_flags) || ++ (sec->sh.sh_entsize != sectwin->sh.sh_entsize) || ++ ((sec->sh.sh_addralign != sectwin->sh.sh_addralign) && ++ !is_text_section(sec) && ++ !is_string_section(sec) && ++ !is_rodata_section(sec))) { ++ /* shaddralign of .rodata may be changed from 0 to 8 bytes ++ once string length is over 30 */ ++ ERROR("%s section header details differ from %s", ++ sec->name, sectwin->name); ++ return -1; ++ } + } + + if (is_note_section(sec)) { +-- +2.43.0 + diff --git a/0065-upatch-diff-allow-tls-variable-changes.patch b/0065-upatch-diff-allow-tls-variable-changes.patch new file mode 100644 index 0000000000000000000000000000000000000000..78e77ee73cf28f30842a6ebe65175b29160cb4d7 --- /dev/null +++ b/0065-upatch-diff-allow-tls-variable-changes.patch @@ -0,0 +1,29 @@ +From 92d344dffe9100be71e2af3c3fcd9aaea3919bf1 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 28 Apr 2025 15:28:45 +0800 +Subject: [PATCH] upatch-diff: allow tls variable changes + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 9c3bc7e..371bb81 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -837,11 +837,6 @@ static int verify_symbol_patchability(struct upatch_elf *uelf) + if (sym->include == 0) { + continue; + } +- if (sym->type == STT_TLS) { +- log_warn("Symbol '%s' is included, but TLS is not supported\n", +- sym->name); +- err_count++; +- } + if (sym->type == STT_GNU_IFUNC) { + log_warn("Symbol '%s' is included, but IFUNC is not supported\n", + sym->name); +-- +2.43.0 + diff --git a/0066-upatch-diff-allow-delete-local-static-variables.patch b/0066-upatch-diff-allow-delete-local-static-variables.patch new file mode 100644 index 0000000000000000000000000000000000000000..4f7b24b4983296a2ab51161e278e3cd89a3d0010 --- /dev/null +++ b/0066-upatch-diff-allow-delete-local-static-variables.patch @@ -0,0 +1,39 @@ +From 0f755236dd37724b9176b29dba3ec85e5f4456dc Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 28 Apr 2025 17:26:52 +0800 +Subject: [PATCH] upatch-diff: allow delete local static variables + +Signed-off-by: renoseven +--- + upatch-diff/elf-correlate.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/upatch-diff/elf-correlate.c b/upatch-diff/elf-correlate.c +index 35039b2..56ee48c 100644 +--- a/upatch-diff/elf-correlate.c ++++ b/upatch-diff/elf-correlate.c +@@ -266,8 +266,9 @@ static void check_static_variable_correlate(struct upatch_elf *uelf_source, + continue; + } + if (!sym->twin || !relasec->twin) { +- ERROR("reference to static local variable %s in %s was removed", ++ log_warn("reference to static local variable %s in %s was removed", + sym->name, section_function_name(relasec)); ++ continue; + } + if (!find_static_twin_ref(relasec->twin, sym)) { + ERROR("static local %s has been correlated with %s, " +@@ -424,8 +425,9 @@ void upatch_correlate_static_local_variables(struct upatch_elf *uelf_source, + + patched_sym = find_static_twin(relasec, sym); + if (!patched_sym) { +- ERROR("reference to static local variable %s in %s was removed", ++ log_warn("reference to static local variable %s in %s was removed", + sym->name, section_function_name(relasec)); ++ continue; + } + + patched_bundled = (patched_sym == patched_sym->sec->sym) ? 1 : 0; +-- +2.43.0 + diff --git a/0067-upatch-diff-fix-lookup_relf-returns-wrong-sympos-iss.patch b/0067-upatch-diff-fix-lookup_relf-returns-wrong-sympos-iss.patch new file mode 100644 index 0000000000000000000000000000000000000000..8c93663a8d1f6371a25638e62ec8041eb34d1ea0 --- /dev/null +++ b/0067-upatch-diff-fix-lookup_relf-returns-wrong-sympos-iss.patch @@ -0,0 +1,41 @@ +From 98dd69b509f30ba01ba4dc2310f541c661f62064 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 28 Apr 2025 17:28:55 +0800 +Subject: [PATCH] upatch-diff: fix lookup_relf() returns wrong sympos issue + +Signed-off-by: renoseven +--- + upatch-diff/running-elf.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/upatch-diff/running-elf.c b/upatch-diff/running-elf.c +index d9c1d6f..b4d6d24 100644 +--- a/upatch-diff/running-elf.c ++++ b/upatch-diff/running-elf.c +@@ -125,14 +125,12 @@ bool lookup_relf(struct running_elf *relf, struct symbol *lookup_sym, + struct lookup_result *result) + { + struct debug_symbol *symbol = NULL; +- unsigned long sympos = 0; + + log_debug("looking up symbol '%s'\n", lookup_sym->name); + memset(result, 0, sizeof(*result)); + + for (int i = 0; i < relf->obj_nr; i++) { + symbol = &relf->obj_syms[i]; +- sympos++; + + if (result->symbol != NULL && symbol->type == STT_FILE) { + break; +@@ -149,7 +147,7 @@ bool lookup_relf(struct running_elf *relf, struct symbol *lookup_sym, + } + + result->symbol = symbol; +- result->sympos = sympos; ++ result->sympos = (unsigned long)i; + result->global = + ((symbol->bind == STB_GLOBAL) || (symbol->bind == STB_WEAK)); + log_debug("found symbol '%s'\n", lookup_sym->name); +-- +2.43.0 + diff --git a/0068-upatch-diff-change-include-ignored-grouped-data-type.patch b/0068-upatch-diff-change-include-ignored-grouped-data-type.patch new file mode 100644 index 0000000000000000000000000000000000000000..82fd4115c8d926efa6882ea43455614d2551b986 --- /dev/null +++ b/0068-upatch-diff-change-include-ignored-grouped-data-type.patch @@ -0,0 +1,163 @@ +From 40dcb22fb74c4c61e5419b1e87cce6526ceebae2 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 28 Apr 2025 16:16:09 +0800 +Subject: [PATCH] upatch-diff: change include & ignored & grouped data type to + bool + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 26 +++++++++++++------------- + upatch-diff/elf-debug.c | 4 ++-- + upatch-diff/upatch-elf.h | 8 ++++---- + 3 files changed, 19 insertions(+), 19 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 371bb81..0c2c22d 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -542,7 +542,7 @@ static void mark_grouped_sections(struct upatch_elf *uelf) + if (!sec) { + ERROR("Group section not found"); + } +- sec->grouped = 1; ++ sec->grouped = true; + log_debug("Marking section '%s' (%d) as grouped\n", + sec->name, sec->index); + data++; +@@ -724,12 +724,12 @@ static void include_special_local_section(struct upatch_elf *uelf) { + if (sym->sec && sym->bind == STB_LOCAL && + sym->status == SAME && !sym->sec->include) { + sym->sym.st_other |= SYM_OTHER; +- sym->sec->include = 1; ++ sym->sec->include = true; + sym->sec->data->d_buf = NULL; + sym->sec->data->d_size = 0; + // arm error: (.debug_info+0x...) undefined reference to `no symbol' + if (sym->sec->secsym) { +- sym->sec->secsym->include = 1; ++ sym->sec->secsym->include = true; + } + } + } +@@ -739,7 +739,7 @@ static void include_special_local_section(struct upatch_elf *uelf) { + static void include_section(struct section *sec); + static void include_symbol(struct symbol *sym) + { +- if ((sym == NULL) || (sym->include != 0)) { ++ if ((sym == NULL) || sym->include) { + return; + } + /* +@@ -749,7 +749,7 @@ static void include_symbol(struct symbol *sym) + */ + log_debug("Include symbol '%s', status: %s\n", + sym->name, status_str(sym->status)); +- sym->include = 1; ++ sym->include = true; + /* + * For a function/object symbol, if it has a section, we only need to + * include the section if it has changed. Otherwise the symbol will be +@@ -765,13 +765,13 @@ static void include_symbol(struct symbol *sym) + + static void include_section(struct section *sec) + { +- if ((sec == NULL) || (sec->include != 0)) { ++ if ((sec == NULL) || sec->include) { + return; + } + + log_debug("Include section '%s', status: %s\n", + sec->name, status_str(sec->status)); +- sec->include = 1; ++ sec->include = true; + + if (is_rela_section(sec)) { + struct rela *rela = NULL; +@@ -834,7 +834,7 @@ static int verify_symbol_patchability(struct upatch_elf *uelf) + + struct symbol *sym = NULL; + list_for_each_entry(sym, &uelf->symbols, list) { +- if (sym->include == 0) { ++ if (!sym->include) { + continue; + } + if (sym->type == STT_GNU_IFUNC) { +@@ -853,22 +853,22 @@ static int verify_section_patchability(struct upatch_elf *uelf) + + struct section *sec = NULL; + list_for_each_entry(sec, &uelf->sections, list) { +- if ((sec->status == NEW) && (sec->include == 0)) { ++ if ((sec->status == NEW) && !sec->include) { + // new sections should be included + log_warn("Section '%s' is %s, but it is not included\n", + sec->name, status_str(sec->status)); + err_count++; +- } else if ((sec->status == CHANGED) && (sec->include == 0)) { +- // changed sections should be included, except rela & debug section ++ } else if ((sec->status == CHANGED) && !sec->include) { ++ // changed sections should be included + if (is_rela_section(sec) || is_debug_section(sec)) { + continue; + } + log_warn("Section '%s' is %s, but it is not included\n", + sec->name, status_str(sec->status)); + err_count++; +- } else if ((sec->status == CHANGED) && (sec->include != 0)) { ++ } else if ((sec->status == CHANGED) && sec->include) { + // changed group section cannot be included +- if (is_group_section(sec) || (sec->grouped != 0)) { ++ if (is_group_section(sec) || sec->grouped) { + log_warn("Section '%s' is %s, but it is not supported\n", + sec->name, status_str(sec->status)); + err_count++; +diff --git a/upatch-diff/elf-debug.c b/upatch-diff/elf-debug.c +index 983bf03..fd95fc8 100644 +--- a/upatch-diff/elf-debug.c ++++ b/upatch-diff/elf-debug.c +@@ -80,7 +80,7 @@ void upatch_print_changes(struct upatch_elf *uelf) + log_normal("Included symbol\n"); + log_normal("------------------------------\n"); + list_for_each_entry(sym, &uelf->symbols, list) { +- if (sym->include != 0) { ++ if (sym->include) { + log_normal("idx: %04u, name: '%s', status: %s\n", + sym->index, sym->name, status_str(sym->status)); + } +@@ -91,7 +91,7 @@ void upatch_print_changes(struct upatch_elf *uelf) + log_normal("Included section\n"); + log_normal("------------------------------\n"); + list_for_each_entry(sec, &uelf->sections, list) { +- if (sec->include != 0) { ++ if (sec->include) { + log_normal("idx: %04u, name: '%s', status: %s\n", + sec->index, sec->name, status_str(sec->status)); + } +diff --git a/upatch-diff/upatch-elf.h b/upatch-diff/upatch-elf.h +index 030feca..653439e 100644 +--- a/upatch-diff/upatch-elf.h ++++ b/upatch-diff/upatch-elf.h +@@ -71,9 +71,9 @@ struct section { + enum data_source data_source; + enum data_source dbuf_source; + GElf_Shdr sh; +- int ignore; +- int include; +- int grouped; ++ bool ignored; ++ bool include; ++ bool grouped; + unsigned int index; + enum status status; + union { +@@ -118,7 +118,7 @@ struct symbol { + unsigned char type; + enum status status; + union { +- int include; /* used in the patched elf */ ++ bool include; /* used in the patched elf */ + enum symbol_strip strip; /* used in the output elf */ + }; + }; +-- +2.43.0 + diff --git a/0069-upatch-diff-compare-symbol-by-checking-it-s-section-.patch b/0069-upatch-diff-compare-symbol-by-checking-it-s-section-.patch new file mode 100644 index 0000000000000000000000000000000000000000..ed6607f1a3bdfdf522a63b8f741277a6e6eec67a --- /dev/null +++ b/0069-upatch-diff-compare-symbol-by-checking-it-s-section-.patch @@ -0,0 +1,128 @@ +From 2b288b188223413ac9b65c93e887720a9f918970 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 28 Apr 2025 15:19:15 +0800 +Subject: [PATCH] upatch-diff: compare symbol by checking it's section & + relocation + +Signed-off-by: renoseven +--- + upatch-diff/elf-compare.c | 63 ++++++++++++++++++++++----------------- + 1 file changed, 36 insertions(+), 27 deletions(-) + +diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c +index 56451af..b461c2a 100644 +--- a/upatch-diff/elf-compare.c ++++ b/upatch-diff/elf-compare.c +@@ -35,32 +35,42 @@ static void compare_correlated_symbol(struct symbol *sym, struct symbol *twin) + { + // symbol type & binding cannot be changed + if (sym->type != twin->type) { +- ERROR("symbol '%s' type mismatched", sym->name); ++ ERROR("Symbol '%s' type mismatched", sym->name); + } + if (sym->sym.st_info != twin->sym.st_info) { +- ERROR("symbol '%s' binding mismatched", sym->name); ++ ERROR("Symbol '%s' st_info mismatched", sym->name); + } + // object symbol size cannot be changed + if ((sym->type == STT_OBJECT) && (sym->sym.st_size != twin->sym.st_size)) { +- ERROR("symbol '%s' object size mismatched", sym->name); ++ ERROR("Symbol '%s' object size mismatched", sym->name); + } + +- // compare symbol sections +- if ((sym->sec != NULL) && (twin->sec != NULL)) { +- // symbol section correlation cannot be changed +- if (sym->sec->twin != twin->sec) { +- ERROR("symbol '%s' section mismatched", sym->name); +- } +- compare_correlated_section(sym->sec, twin->sec); +- sym->status = sym->sec->status; ++ /* ++ * For local symbols, we handle them based on their matching sections. ++ */ ++ if ((sym->sym.st_shndx == SHN_UNDEF) || (sym->sym.st_shndx == SHN_ABS)) { ++ sym->status = SAME; ++ return; + } + +- if ((sym->sym.st_shndx == SHN_UNDEF) || (sym->sym.st_shndx == SHN_ABS)) { ++ if ((sym->sec == NULL) || (sym->sym.st_shndx == SHN_ABS)) { ++ ERROR("Symbol '%s' don't have section\n", sym->name); ++ } ++ ++ if (sym->sec->twin != twin->sec) { ++ ERROR("Symbol '%s' section mismatched", sym->name); ++ } ++ ++ compare_correlated_section(sym->sec, twin->sec); ++ if (sym->sec->status == CHANGED) { ++ sym->status = CHANGED; ++ } else if (!is_rela_section(sym->sec) && ++ (sym->sec->rela != NULL) && ++ (sym->sec->rela->status == CHANGED)) { ++ sym->status = CHANGED; ++ } else { + sym->status = SAME; + } +- /* +- * For local symbols, we handle them based on their matching sections. +- */ + } + + void upatch_compare_symbols(struct upatch_elf *uelf) +@@ -128,22 +138,21 @@ static void compare_correlated_nonrela_section(struct section *sec, + } + + // we may change status of sec, they are not same +-static int compare_correlated_section(struct section *sec, +- struct section *sectwin) ++static int compare_correlated_section(struct section *sec, struct section *twin) + { + /* compare section headers */ + if (!is_debug_section(sec)) { +- if ((sec->sh.sh_type != sectwin->sh.sh_type) || +- (sec->sh.sh_flags != sectwin->sh.sh_flags) || +- (sec->sh.sh_entsize != sectwin->sh.sh_entsize) || +- ((sec->sh.sh_addralign != sectwin->sh.sh_addralign) && ++ if ((sec->sh.sh_type != twin->sh.sh_type) || ++ (sec->sh.sh_flags != twin->sh.sh_flags) || ++ (sec->sh.sh_entsize != twin->sh.sh_entsize) || ++ ((sec->sh.sh_addralign != twin->sh.sh_addralign) && + !is_text_section(sec) && + !is_string_section(sec) && + !is_rodata_section(sec))) { + /* shaddralign of .rodata may be changed from 0 to 8 bytes + once string length is over 30 */ + ERROR("%s section header details differ from %s", +- sec->name, sectwin->name); ++ sec->name, twin->name); + return -1; + } + } +@@ -159,17 +168,17 @@ static int compare_correlated_section(struct section *sec, + goto out; + } + /* compare file size and data size(memory size) */ +- if (sec->sh.sh_size != sectwin->sh.sh_size || +- sec->data->d_size != sectwin->data->d_size || +- (sec->rela && !sectwin->rela) || (!sec->rela && sectwin->rela)) { ++ if (sec->sh.sh_size != twin->sh.sh_size || ++ sec->data->d_size != twin->data->d_size || ++ (sec->rela && !twin->rela) || (!sec->rela && twin->rela)) { + sec->status = CHANGED; + goto out; + } + + if (is_rela_section(sec)) { +- compare_correlated_rela_section(sec, sectwin); ++ compare_correlated_rela_section(sec, twin); + } else { +- compare_correlated_nonrela_section(sec, sectwin); ++ compare_correlated_nonrela_section(sec, twin); + } + + out: +-- +2.43.0 + diff --git a/0070-upatch-diff-ignore-debug-sections.patch b/0070-upatch-diff-ignore-debug-sections.patch new file mode 100644 index 0000000000000000000000000000000000000000..f3730f54ce7f0f09ea9d388d8d36661909cd1dd0 --- /dev/null +++ b/0070-upatch-diff-ignore-debug-sections.patch @@ -0,0 +1,296 @@ +From 06a7b099a67de722d197951becd63e744d54e499 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 28 Apr 2025 17:24:03 +0800 +Subject: [PATCH] upatch-diff: ignore debug sections + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 44 ++++++++++++++++++++------------ + upatch-diff/elf-common.h | 5 ++++ + upatch-diff/elf-compare.c | 32 +++++++++++++---------- + upatch-diff/elf-correlate.c | 3 +++ + upatch-diff/elf-create.c | 16 ++++++++++-- + upatch-diff/elf-debug.c | 7 +++-- + 6 files changed, 71 insertions(+), 36 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 0c2c22d..a3bc988 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -681,20 +681,28 @@ static void replace_section_syms(struct upatch_elf *uelf) + static void mark_ignored_sections(struct upatch_elf *uelf) + { + static const char *const IGNORED_SECTIONS[] = { ++ ".eh_frame", ++ ".note", ++ ".debug_", + ".comment", + ".discard", + ".rela.discard", + ".GCC.command.line", + }; ++ static const size_t IGNORED_SECTION_NUM = ++ sizeof(IGNORED_SECTIONS) / sizeof(IGNORED_SECTIONS[0]); + +- for (size_t i = 0; i < ARRAY_SIZE(IGNORED_SECTIONS); i++) { +- const char *const ignored_name = IGNORED_SECTIONS[i]; +- const size_t name_len = strlen(ignored_name); +- +- struct section *sec = NULL; +- list_for_each_entry(sec, &uelf->sections, list) { +- if (strncmp(sec->name, ignored_name, name_len) == 0) { +- sec->status = SAME; ++ struct section *sec = NULL; ++ list_for_each_entry(sec, &uelf->sections, list) { ++ for (size_t i = 0; i < IGNORED_SECTION_NUM; i++) { ++ const char *const ignored_name = IGNORED_SECTIONS[i]; ++ const size_t name_len = strlen(ignored_name); ++ const char *sec_name = is_rela_section(sec) ? ++ sec->base->name : sec->name; ++ if (strncmp(sec_name, ignored_name, name_len) == 0) { ++ sec->ignored = true; ++ log_debug("Marking section '%s' (%d) as ignored\n", ++ sec->name, sec->index); + break; + } + } +@@ -790,6 +798,9 @@ static void include_standard_elements(struct upatch_elf *uelf) + struct section *sec = NULL; + + list_for_each_entry(sec, &uelf->sections, list) { ++ if (sec->ignored) { ++ continue; ++ } + if (is_symtab_section(sec) || is_strtab_section(sec)) { + include_section(sec); + } +@@ -804,7 +815,7 @@ static int include_changes(struct upatch_elf *uelf) + + struct symbol *sym = NULL; + list_for_each_entry(sym, &uelf->symbols, list) { +- if (sym->status == SAME) { ++ if ((sym->status == SAME) || is_symbol_ignored(sym)) { + continue; + } + +@@ -816,8 +827,7 @@ static int include_changes(struct upatch_elf *uelf) + include_symbol(sym); + count++; + } else if (sym->type == STT_SECTION) { +- if ((sym->sec != NULL) && +- (is_rela_section(sym->sec) || is_debug_section(sym->sec))) { ++ if ((sym->sec != NULL) && is_rela_section(sym->sec)) { + continue; + } + include_symbol(sym); +@@ -853,6 +863,9 @@ static int verify_section_patchability(struct upatch_elf *uelf) + + struct section *sec = NULL; + list_for_each_entry(sec, &uelf->sections, list) { ++ if (sec->ignored) { ++ continue; ++ } + if ((sec->status == NEW) && !sec->include) { + // new sections should be included + log_warn("Section '%s' is %s, but it is not included\n", +@@ -860,7 +873,7 @@ static int verify_section_patchability(struct upatch_elf *uelf) + err_count++; + } else if ((sec->status == CHANGED) && !sec->include) { + // changed sections should be included +- if (is_rela_section(sec) || is_debug_section(sec)) { ++ if (is_rela_section(sec)) { + continue; + } + log_warn("Section '%s' is %s, but it is not included\n", +@@ -995,6 +1008,9 @@ int main(int argc, char*argv[]) + detect_child_functions(&uelf_source); + detect_child_functions(&uelf_patched); + ++ mark_ignored_sections(&uelf_source); ++ mark_ignored_sections(&uelf_patched); ++ + mark_grouped_sections(&uelf_patched); + + replace_section_syms(&uelf_source); +@@ -1003,10 +1019,6 @@ int main(int argc, char*argv[]) + upatch_correlate_elf(&uelf_source, &uelf_patched); + upatch_correlate_static_local_variables(&uelf_source, &uelf_patched); + +- /* Now, we can only check uelf_patched, all we need is in the twin part */ +- /* Also, we choose part of uelf_patched and output new object */ +- mark_ignored_sections(&uelf_patched); +- + upatch_compare_correlated_elements(&uelf_patched); + mark_file_symbols(&uelf_source); + find_debug_symbol(&uelf_source, &relf); +diff --git a/upatch-diff/elf-common.h b/upatch-diff/elf-common.h +index 5e63b09..3454c21 100644 +--- a/upatch-diff/elf-common.h ++++ b/upatch-diff/elf-common.h +@@ -150,6 +150,11 @@ static inline bool is_debug_section(struct section *sec) + !strncmp(name, ".eh_frame", 9); + } + ++static inline bool is_symbol_ignored(struct symbol *sym) ++{ ++ return (sym->sec != NULL) && sym->sec->ignored; ++} ++ + static inline struct symbol *find_symbol_by_index(struct list_head *list, unsigned int index) + { + struct symbol *sym; +diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c +index b461c2a..b37167c 100644 +--- a/upatch-diff/elf-compare.c ++++ b/upatch-diff/elf-compare.c +@@ -78,6 +78,9 @@ void upatch_compare_symbols(struct upatch_elf *uelf) + struct symbol *sym; + + list_for_each_entry(sym, &uelf->symbols, list) { ++ if (is_symbol_ignored(sym)) { ++ continue; ++ } + if (sym->twin) { + compare_correlated_symbol(sym, sym->twin); + } else { +@@ -141,20 +144,18 @@ static void compare_correlated_nonrela_section(struct section *sec, + static int compare_correlated_section(struct section *sec, struct section *twin) + { + /* compare section headers */ +- if (!is_debug_section(sec)) { +- if ((sec->sh.sh_type != twin->sh.sh_type) || +- (sec->sh.sh_flags != twin->sh.sh_flags) || +- (sec->sh.sh_entsize != twin->sh.sh_entsize) || +- ((sec->sh.sh_addralign != twin->sh.sh_addralign) && +- !is_text_section(sec) && +- !is_string_section(sec) && +- !is_rodata_section(sec))) { +- /* shaddralign of .rodata may be changed from 0 to 8 bytes +- once string length is over 30 */ +- ERROR("%s section header details differ from %s", +- sec->name, twin->name); +- return -1; +- } ++ if ((sec->sh.sh_type != twin->sh.sh_type) || ++ (sec->sh.sh_flags != twin->sh.sh_flags) || ++ (sec->sh.sh_entsize != twin->sh.sh_entsize) || ++ ((sec->sh.sh_addralign != twin->sh.sh_addralign) && ++ !is_text_section(sec) && ++ !is_string_section(sec) && ++ !is_rodata_section(sec))) { ++ /* shaddralign of .rodata may be changed from 0 to 8 bytes ++ once string length is over 30 */ ++ ERROR("%s section header details differ from %s", ++ sec->name, twin->name); ++ return -1; + } + + if (is_note_section(sec)) { +@@ -213,6 +214,9 @@ void upatch_compare_sections(struct upatch_elf *uelf) + struct section *sec = NULL; + + list_for_each_entry(sec, &uelf->sections, list) { ++ if (sec->ignored) { ++ continue; ++ } + if (sec->twin == NULL) { + sec->status = NEW; + } else { +diff --git a/upatch-diff/elf-correlate.c b/upatch-diff/elf-correlate.c +index 56ee48c..b39ce7d 100644 +--- a/upatch-diff/elf-correlate.c ++++ b/upatch-diff/elf-correlate.c +@@ -54,6 +54,9 @@ void upatch_correlate_symbols(struct upatch_elf *uelf_source, + struct symbol *sym_patched; + + list_for_each_entry(sym_orig, &uelf_source->symbols, list) { ++ if (is_symbol_ignored(sym_orig)) { ++ continue; ++ } + if (sym_orig->twin) { + continue; + } +diff --git a/upatch-diff/elf-create.c b/upatch-diff/elf-create.c +index 20d1994..112be83 100644 +--- a/upatch-diff/elf-create.c ++++ b/upatch-diff/elf-create.c +@@ -221,8 +221,7 @@ static bool need_dynrela(struct running_elf *relf, struct section *relasec, + { + struct lookup_result symbol; + +- if (is_debug_section(relasec) || +- is_note_section(relasec)) { ++ if (relasec->ignored) { + return false; + } + +@@ -521,6 +520,9 @@ void upatch_create_shstrtab(struct upatch_elf *uelf) + /* determine size of string table */ + size = 1; + list_for_each_entry(sec, &uelf->sections, list) { ++ if (sec->ignored) { ++ continue; ++ } + size += strlen(sec->name) + 1; + } + +@@ -531,6 +533,9 @@ void upatch_create_shstrtab(struct upatch_elf *uelf) + + offset = 1; + list_for_each_entry(sec, &uelf->sections, list) { ++ if (sec->ignored) { ++ continue; ++ } + len = strlen(sec->name) + 1; + sec->sh.sh_name = (unsigned int)offset; + memcpy(buf + offset, sec->name, len); +@@ -551,6 +556,9 @@ void upatch_create_shstrtab(struct upatch_elf *uelf) + log_debug("\n"); + + list_for_each_entry(sec, &uelf->sections, list) { ++ if (sec->ignored) { ++ continue; ++ } + log_debug("%s @ shstrtab offset %d\n", sec->name, sec->sh.sh_name); + } + } +@@ -713,6 +721,10 @@ void upatch_write_output_elf(struct upatch_elf *uelf, Elf *elf, + + /* add changed sections */ + list_for_each_entry(sec, &uelf->sections, list) { ++ if (sec->ignored) { ++ continue; ++ } ++ + scn = elf_newscn(elfout); + if (!scn) { + ERROR("elf_newscn failed."); +diff --git a/upatch-diff/elf-debug.c b/upatch-diff/elf-debug.c +index fd95fc8..90e112b 100644 +--- a/upatch-diff/elf-debug.c ++++ b/upatch-diff/elf-debug.c +@@ -110,10 +110,10 @@ void upatch_dump_kelf(struct upatch_elf *uelf) + log_debug("%02d %s (%s)", + sec->index, sec->name, status_str(sec->status)); + if (is_rela_section(sec)) { +- log_debug(", base-> %s\n", sec->base->name); +- if (is_debug_section(sec) || is_note_section(sec)) { +- goto next; ++ if (sec->ignored) { ++ continue; + } ++ log_debug(", base-> %s\n", sec->base->name); + log_debug("rela section expansion\n"); + list_for_each_entry(rela, &sec->relas, list) { + log_debug("sym %d, offset %ld, type %d, %s %s %ld\n", +@@ -133,7 +133,6 @@ void upatch_dump_kelf(struct upatch_elf *uelf) + log_debug(", rela-> %s", sec->rela->name); + } + } +-next: + log_debug("\n"); + } + +-- +2.43.0 + diff --git a/0071-upatch-diff-allow-sh_flags-sh_addralign-changes.patch b/0071-upatch-diff-allow-sh_flags-sh_addralign-changes.patch new file mode 100644 index 0000000000000000000000000000000000000000..6066748080304445879487e27bb3630811e5ccf0 --- /dev/null +++ b/0071-upatch-diff-allow-sh_flags-sh_addralign-changes.patch @@ -0,0 +1,50 @@ +From e02b463ad3a5c09baa49961ac4e872d2c6b3049d Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 28 Apr 2025 17:40:43 +0800 +Subject: [PATCH] upatch-diff: allow sh_flags & sh_addralign changes + +Signed-off-by: renoseven +--- + upatch-diff/elf-compare.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c +index b37167c..7ccc952 100644 +--- a/upatch-diff/elf-compare.c ++++ b/upatch-diff/elf-compare.c +@@ -143,20 +143,23 @@ static void compare_correlated_nonrela_section(struct section *sec, + // we may change status of sec, they are not same + static int compare_correlated_section(struct section *sec, struct section *twin) + { +- /* compare section headers */ ++ /* We allow sh_flags and sh_addralign changes. ++ When we change the initial value of variables ++ sh_flags & sh_addralign may change in .rodata section */ + if ((sec->sh.sh_type != twin->sh.sh_type) || +- (sec->sh.sh_flags != twin->sh.sh_flags) || +- (sec->sh.sh_entsize != twin->sh.sh_entsize) || +- ((sec->sh.sh_addralign != twin->sh.sh_addralign) && +- !is_text_section(sec) && +- !is_string_section(sec) && +- !is_rodata_section(sec))) { +- /* shaddralign of .rodata may be changed from 0 to 8 bytes +- once string length is over 30 */ ++ (sec->sh.sh_entsize != twin->sh.sh_entsize)) { + ERROR("%s section header details differ from %s", + sec->name, twin->name); + return -1; + } ++ if (sec->sh.sh_flags != twin->sh.sh_flags) { ++ log_warn("Section '%s' sh_flags changed from %ld to %ld\n", ++ sec->name, sec->sh.sh_flags, twin->sh.sh_flags); ++ } ++ if (sec->sh.sh_addralign != twin->sh.sh_addralign) { ++ log_warn("Section '%s' sh_addralign changed from %ld to %ld\n", ++ sec->name, sec->sh.sh_addralign, twin->sh.sh_addralign); ++ } + + if (is_note_section(sec)) { + sec->status = SAME; +-- +2.43.0 + diff --git a/0072-upatch-diff-fix-null-symbol-lookup-error.patch b/0072-upatch-diff-fix-null-symbol-lookup-error.patch new file mode 100644 index 0000000000000000000000000000000000000000..8cd0cedfb71f977d0a1db144374b805b9f0dc410 --- /dev/null +++ b/0072-upatch-diff-fix-null-symbol-lookup-error.patch @@ -0,0 +1,48 @@ +From cf34c2b14c93cd56dc8bb2fab578801980823063 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 30 Apr 2025 18:45:00 +0800 +Subject: [PATCH] upatch-diff: fix null symbol lookup error + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 7 ++++++- + upatch-diff/elf-common.h | 4 +++- + 2 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index a3bc988..1de2f1b 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -805,8 +805,13 @@ static void include_standard_elements(struct upatch_elf *uelf) + include_section(sec); + } + } ++ + /* include the NULL symbol */ +- include_symbol(list_entry(uelf->symbols.next, struct symbol, list)); ++ struct symbol *sym = find_symbol_by_index(&uelf->symbols, 0); ++ if (sym == NULL) { ++ ERROR("Cannot find null symbol"); ++ } ++ include_symbol(sym); + } + + static int include_changes(struct upatch_elf *uelf) +diff --git a/upatch-diff/elf-common.h b/upatch-diff/elf-common.h +index 3454c21..89d238a 100644 +--- a/upatch-diff/elf-common.h ++++ b/upatch-diff/elf-common.h +@@ -273,7 +273,9 @@ static inline unsigned int absolute_rela_type(struct upatch_elf *uelf) + + static inline bool is_null_sym(struct symbol *sym) + { +- return !strlen(sym->name); ++ return (sym->type == STT_NOTYPE) && ++ (sym->bind == STB_LOCAL) && ++ (strlen(sym->name) == 0); + } + + static inline bool is_file_sym(struct symbol *sym) +-- +2.43.0 + diff --git a/0073-upatch-diff-use-kpatch-way-to-deal-with-static-local.patch b/0073-upatch-diff-use-kpatch-way-to-deal-with-static-local.patch new file mode 100644 index 0000000000000000000000000000000000000000..94db7302828aeadb5f3e9b130eac3a0b9e4901e4 --- /dev/null +++ b/0073-upatch-diff-use-kpatch-way-to-deal-with-static-local.patch @@ -0,0 +1,280 @@ +From fde9ebc5ede3fd24b0674651358b06b333e0e039 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Tue, 29 Apr 2025 16:55:42 +0800 +Subject: [PATCH] upatch-diff: use kpatch way to deal with static local + variables + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 13 +++++ + upatch-diff/elf-common.c | 91 ++++++++++++++++++++++++++++++-- + upatch-diff/elf-common.h | 9 ++++ + upatch-diff/elf-compare.c | 14 +++-- + upatch-diff/elf-correlate.c | 41 +++++++++----- + 5 files changed, 145 insertions(+), 23 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 1de2f1b..c911129 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -758,6 +758,13 @@ static void include_symbol(struct symbol *sym) + log_debug("Include symbol '%s', status: %s\n", + sym->name, status_str(sym->status)); + sym->include = true; ++ /* ++ * For special static symbols, we need include it's section ++ * to ensure we don't get link error. ++ */ ++ if (is_special_static_symbol(sym)) { ++ sym->sec->include = true; ++ } + /* + * For a function/object symbol, if it has a section, we only need to + * include the section if it has changed. Otherwise the symbol will be +@@ -852,6 +859,12 @@ static int verify_symbol_patchability(struct upatch_elf *uelf) + if (!sym->include) { + continue; + } ++ if ((sym->bind == STB_LOCAL) && (sym->sym.st_shndx == SHN_UNDEF) && ++ (sym->index != 0)) { ++ log_warn("Symbol '%s' is local, but sh_shndx is SHN_UNDEF\n", ++ sym->name); ++ err_count++; ++ } + if (sym->type == STT_GNU_IFUNC) { + log_warn("Symbol '%s' is included, but IFUNC is not supported\n", + sym->name); +diff --git a/upatch-diff/elf-common.c b/upatch-diff/elf-common.c +index 5aa35f1..6e13c34 100644 +--- a/upatch-diff/elf-common.c ++++ b/upatch-diff/elf-common.c +@@ -26,6 +26,89 @@ + + #include "elf-common.h" + ++static bool is_dynamic_debug_symbol(struct symbol *sym) ++{ ++ static const char *SEC_NAMES[] = { ++ "__verbose", ++ "__dyndbg", ++ NULL, ++ }; ++ ++ if ((sym->type == STT_OBJECT) || (sym->type == STT_SECTION)) { ++ const char **sec_name; ++ for (sec_name = SEC_NAMES; *sec_name; sec_name++) { ++ if (strcmp(sym->sec->name, *sec_name) == 0) { ++ return true; ++ } ++ } ++ } ++ ++ return false; ++} ++ ++bool is_special_static_symbol(struct symbol *sym) ++{ ++ static const char *SYM_NAMES[] = { ++ ".__key", ++ ".__warned", ++ ".__already_done.", ++ ".__func__", ++ ".__FUNCTION__", ++ ".__PRETTY_FUNCTION__", ++ "._rs", ++ ".CSWTCH", ++ "._entry", ++ ".C", ++ NULL, ++ }; ++ ++ if (sym == NULL) { ++ return false; ++ } ++ ++ /* pr_debug() uses static local variables in __verbose or __dyndbg section */ ++ if (is_dynamic_debug_symbol(sym)) { ++ return true; ++ } ++ ++ if (sym->type == STT_SECTION) { ++ /* make sure section is bundled */ ++ if (is_rela_section(sym->sec) || (sym->sec->sym == NULL)) { ++ return false; ++ } ++ /* use bundled object object/function symbol for matching */ ++ sym = sym->sec->sym; ++ } ++ ++ if ((sym->type != STT_OBJECT) || (sym->bind != STB_LOCAL)) { ++ return false; ++ } ++ if (!strcmp(sym->sec->name, ".data.once")) { ++ return true; ++ } ++ ++ const char **sym_name; ++ for (sym_name = SYM_NAMES; *sym_name; sym_name++) { ++ /* Check gcc-style statics: '.' */ ++ if (strcmp(sym->name, (*sym_name + 1)) == 0) { ++ return true; ++ } ++ /* Check clang-style statics: '.' */ ++ if (strstr(sym->name, *sym_name)) { ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++bool is_special_static_section(struct section *sec) ++{ ++ struct symbol *sym = is_rela_section(sec) ? ++ sec->base->secsym : sec->secsym; ++ return is_special_static_symbol(sym); ++} ++ + int mangled_strcmp(char *str1, char *str2) + { + /* +@@ -78,11 +161,9 @@ bool is_normal_static_local(struct symbol *sym) + if (!strchr(sym->name, '.')) { + return false; + } +- +- /* +- * TODO: Special static local variables should never be correlated and should always +- * be included if they are referenced by an included function. +- */ ++ if (is_special_static_symbol(sym)) { ++ return false; ++ } + return true; + } + +diff --git a/upatch-diff/elf-common.h b/upatch-diff/elf-common.h +index 89d238a..672295c 100644 +--- a/upatch-diff/elf-common.h ++++ b/upatch-diff/elf-common.h +@@ -303,4 +303,13 @@ bool is_gcc6_localentry_bundled_sym(struct upatch_elf *); + */ + bool is_mapping_symbol(struct upatch_elf *, struct symbol *); + ++/* ++ * This function detects whether the given symbol is a "special" static local ++ * variable (for lack of a better term). ++ * Special static local variables shoe never be correlated and should always ++ * be included if they are referenced by an included function. ++ */ ++bool is_special_static_symbol(struct symbol *sym); ++bool is_special_static_section(struct section *sec); ++ + #endif +diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c +index 7ccc952..7314a27 100644 +--- a/upatch-diff/elf-compare.c ++++ b/upatch-diff/elf-compare.c +@@ -81,12 +81,14 @@ void upatch_compare_symbols(struct upatch_elf *uelf) + if (is_symbol_ignored(sym)) { + continue; + } +- if (sym->twin) { +- compare_correlated_symbol(sym, sym->twin); +- } else { ++ if (is_special_static_symbol(sym)) { ++ sym->status = SAME; ++ } else if (sym->twin == NULL) { + sym->status = NEW; ++ } else { ++ compare_correlated_symbol(sym, sym->twin); + } +- log_debug("symbol %s is %s\n", sym->name, status_str(sym->status)); ++ log_debug("Symbol '%s' is %s\n", sym->name, status_str(sym->status)); + } + } + +@@ -220,7 +222,9 @@ void upatch_compare_sections(struct upatch_elf *uelf) + if (sec->ignored) { + continue; + } +- if (sec->twin == NULL) { ++ if (is_special_static_section(sec)) { ++ sec->status = SAME; ++ } else if (sec->twin == NULL) { + sec->status = NEW; + } else { + compare_correlated_section(sec, sec->twin); +diff --git a/upatch-diff/elf-correlate.c b/upatch-diff/elf-correlate.c +index b39ce7d..59069a3 100644 +--- a/upatch-diff/elf-correlate.c ++++ b/upatch-diff/elf-correlate.c +@@ -60,17 +60,24 @@ void upatch_correlate_symbols(struct upatch_elf *uelf_source, + if (sym_orig->twin) { + continue; + } ++ /* ++ * Special static local variables should never be correlated ++ * and should always be included if they are referenced by ++ * an included function. ++ */ ++ if (is_special_static_symbol(sym_orig)) { ++ continue; ++ } ++ + /* find matched symbol */ + list_for_each_entry(sym_patched, &uelf_patched->symbols, list) { + if (mangled_strcmp(sym_orig->name, sym_patched->name) || + sym_orig->type != sym_patched->type || sym_patched->twin) { + continue; + } +- /* +- * TODO: Special static local variables should never be correlated +- * and should always be included if they are referenced by +- * an included function. +- */ ++ if (is_special_static_symbol(sym_patched)) { ++ continue; ++ } + /* + * The .LCx symbols point to string literals in + * '.rodata..str1.*' sections. They get included +@@ -148,19 +155,27 @@ void upatch_correlate_sections(struct upatch_elf *uelf_source, + + list_for_each_entry(sec_orig, &uelf_source->sections, list) { + /* already found */ +- if (sec_orig->twin) { ++ if (sec_orig->twin != NULL) { ++ continue; ++ } ++ /* ++ * Special static local variables should never be correlated ++ * and should always be included if they are referenced by ++ * an included function. ++ */ ++ if (is_special_static_section(sec_orig)) { + continue; + } + list_for_each_entry(sec_patched, &uelf_patched->sections, list) { +- if (mangled_strcmp(sec_orig->name, sec_patched->name) || +- sec_patched->twin) { ++ if (sec_patched->twin != NULL) { ++ continue; ++ } ++ if (is_special_static_section(sec_patched)) { ++ continue; ++ } ++ if (mangled_strcmp(sec_orig->name, sec_patched->name)) { + continue; + } +- /* +- * TODO: Special static local variables should never be correlated +- * and should always be included if they are referenced by +- * an included function. +- */ + /* + * Group sections must match exactly to be correlated. + */ +-- +2.43.0 + diff --git a/0074-upatch-diff-remove-intermediate-sections.patch b/0074-upatch-diff-remove-intermediate-sections.patch new file mode 100644 index 0000000000000000000000000000000000000000..8a5869e5d08723292c01f061dca9bcb6114d4cfb --- /dev/null +++ b/0074-upatch-diff-remove-intermediate-sections.patch @@ -0,0 +1,156 @@ +From c4542aef5d2b3b6cfc2c833909d225e10ee448f0 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Tue, 29 Apr 2025 18:11:50 +0800 +Subject: [PATCH] upatch-diff: remove intermediate sections + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 2 - + upatch-diff/elf-create.c | 104 ------------------------------- + upatch-diff/elf-create.h | 2 - + 3 files changed, 108 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index c911129..0b580a9 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -1070,8 +1070,6 @@ int main(int argc, char*argv[]) + + upatch_create_patches_sections(&uelf_out, &relf); + +- upatch_create_intermediate_sections(&uelf_out, &relf); +- + create_kpatch_arch_section(); + + upatch_build_strings_section_data(&uelf_out); +diff --git a/upatch-diff/elf-create.c b/upatch-diff/elf-create.c +index 112be83..139f92d 100644 +--- a/upatch-diff/elf-create.c ++++ b/upatch-diff/elf-create.c +@@ -216,110 +216,6 @@ void upatch_create_patches_sections(struct upatch_elf *uelf, + } + } + +-static bool need_dynrela(struct running_elf *relf, struct section *relasec, +- struct rela *rela) +-{ +- struct lookup_result symbol; +- +- if (relasec->ignored) { +- return false; +- } +- +- if (!lookup_relf(relf, rela->sym, &symbol)) { +- /* relocation is based on new symbol. */ +- return false; +- } +- +- if (rela->sym->bind == STB_LOCAL) { +- if (symbol.global) { +- ERROR("No releated local symbol found.\n"); +- } +- return true; +- } +- +- return false; +-} +- +-/* +- * This function is used to handle relocations which cannot be handled normally +- * +- * Situations: +- * 1. refer to old symbols +- * +- */ +-void upatch_create_intermediate_sections(struct upatch_elf *uelf, +- struct running_elf *relf) +-{ +- struct rela *rela, *rela_safe; +- struct section *relasec, *usym_sec, *urela_sec; +- struct upatch_symbol *usyms; +- struct upatch_relocation *urelas; +- struct symbol *strsym, *usym_sec_sym; +- unsigned int nr = 0, index = 0; +- +- list_for_each_entry(relasec, &uelf->sections, list) { +- if (!is_rela_section(relasec)) { +- continue; +- } +- /* no need to handle upatch meta section. */ +- if (!strcmp(relasec->name, ".rela.upatch.funcs")) { +- continue; +- } +- list_for_each_entry(rela, &relasec->relas, list) { +- nr++; +- if (need_dynrela(relf, relasec, rela)) { +- rela->need_dynrela = 1; +- } +- } +- } +- +- urela_sec = create_section_pair(uelf, ".upatch.relocations", +- sizeof(*urelas), nr); +- urelas = urela_sec->data->d_buf; +- +- usym_sec = create_section_pair(uelf, ".upatch.symbols", +- sizeof(*usyms), nr); +- usyms = usym_sec->data->d_buf; +- +- ALLOC_LINK(usym_sec_sym, &uelf->symbols); +- usym_sec_sym->sec = usym_sec; +- usym_sec_sym->sym.st_info = GELF_ST_INFO(STB_LOCAL, STT_SECTION); +- usym_sec_sym->type = STT_SECTION; +- usym_sec_sym->bind = STB_LOCAL; +- usym_sec_sym->name = ".upatch.symbols"; +- +- strsym = find_symbol_by_name(&uelf->symbols, ".upatch.strings"); +- if (!strsym) { +- ERROR("can't find .upatch.strings symbol.\n"); +- } +- +- list_for_each_entry(relasec, &uelf->sections, list) { +- if (!is_rela_section(relasec)) { +- continue; +- } +- if (!strcmp(relasec->name, ".rela.upatch.funcs") || +- !strcmp(relasec->name, ".rela.upatch.relocations") || +- !strcmp(relasec->name, ".rela.upatch.symbols")) { +- continue; +- } +- list_for_each_entry_safe(rela, rela_safe, &relasec->relas, list) { +- if (!rela->need_dynrela) { +- rela->sym->strip = SYMBOL_USED; +- continue; +- } +- } +- } +- +- log_debug("generate %d dynamic relocations.\n", index); +- +- /* set size to actual number of kyms/krelas */ +- usym_sec->data->d_size = index * sizeof(struct upatch_symbol); +- usym_sec->sh.sh_size = usym_sec->data->d_size; +- +- urela_sec->data->d_size = index * sizeof(struct upatch_relocation); +- urela_sec->sh.sh_size = urela_sec->data->d_size; +-} +- + void upatch_build_strings_section_data(struct upatch_elf *uelf) + { + struct section *sec; +diff --git a/upatch-diff/elf-create.h b/upatch-diff/elf-create.h +index b9efbb3..f18d40b 100644 +--- a/upatch-diff/elf-create.h ++++ b/upatch-diff/elf-create.h +@@ -31,8 +31,6 @@ void upatch_create_strings_elements(struct upatch_elf *); + + void upatch_create_patches_sections(struct upatch_elf *, struct running_elf *); + +-void upatch_create_intermediate_sections(struct upatch_elf *, struct running_elf *); +- + static inline void create_kpatch_arch_section(void) {} + + void upatch_build_strings_section_data(struct upatch_elf *); +-- +2.43.0 + diff --git a/0075-upatch-diff-rewrite-local-symbol-matching-logic.patch b/0075-upatch-diff-rewrite-local-symbol-matching-logic.patch new file mode 100644 index 0000000000000000000000000000000000000000..a5d1df3b085664780cb8d7360e17fe986ef1f3e0 --- /dev/null +++ b/0075-upatch-diff-rewrite-local-symbol-matching-logic.patch @@ -0,0 +1,305 @@ +From d1c15c984d02894046e3c87662725ba624b349bc Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Tue, 29 Apr 2025 18:09:30 +0800 +Subject: [PATCH] upatch-diff: rewrite local symbol matching logic + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 191 ++++++++++++++----------------- + upatch-diff/elf-correlate.c | 4 +- + upatch-diff/upatch-elf.h | 2 +- + 3 files changed, 88 insertions(+), 109 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 0b580a9..3d6edc8 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -329,7 +329,7 @@ static void detect_child_functions(struct upatch_elf *uelf) + } + } + +-static bool discarded_sym(struct running_elf *relf, struct symbol *sym) ++static bool is_discarded_sym(struct running_elf *relf, struct symbol *sym) + { + if (!sym || !sym->sec || !sym->sec->name) { + return false; +@@ -348,140 +348,115 @@ static bool discarded_sym(struct running_elf *relf, struct symbol *sym) + return false; + } + +-enum local_match { +- FOUND, +- NOT_FOUND, +- EMPTY, +-}; +- +-static enum local_match locals_match(struct upatch_elf *uelf, +- struct running_elf *relf, struct symbol *file_sym, int file_sym_idx) ++static struct symbol* match_uelf_local_symbol(struct upatch_elf *uelf, ++ struct symbol *start_sym, struct debug_symbol *relf_sym) + { +- struct symbol *uelf_sym = NULL; +- struct debug_symbol *relf_sym = NULL; +- enum local_match found = EMPTY; +- +- for (int i = file_sym_idx + 1; i < relf->obj_nr; i++) { +- relf_sym = &relf->obj_syms[i]; +- +- if (relf_sym->type == STT_FILE) { ++ struct symbol *uelf_sym = start_sym; ++ list_for_each_entry_continue(uelf_sym, &uelf->symbols, list) { ++ if (uelf_sym->type == STT_FILE) { + break; // find until next file + } +- if (relf_sym->bind != STB_LOCAL) { ++ if (uelf_sym->bind != STB_LOCAL) { + continue; + } +- if ((relf_sym->type != STT_FUNC) && +- (relf_sym->type != STT_OBJECT)) { ++ if ((uelf_sym->type != STT_FUNC) && (uelf_sym->type != STT_OBJECT)) { + continue; + } +- +- found = NOT_FOUND; +- uelf_sym = file_sym; +- list_for_each_entry_continue(uelf_sym, &uelf->symbols, list) { +- if (uelf_sym->type == STT_FILE) { +- break; // find until next file +- } +- if (uelf_sym->bind != STB_LOCAL) { +- continue; +- } +- if ((uelf_sym->type == relf_sym->type) && +- (strcmp(uelf_sym->name, relf_sym->name) == 0)) { +- found = FOUND; +- break; +- } +- } +- +- if (found == NOT_FOUND) { +- log_warn("Cannot find symbol '%s' in %s\n", +- relf_sym->name, g_relf_name); +- return NOT_FOUND; ++ if ((uelf_sym->type != relf_sym->type) || ++ (strcmp(uelf_sym->name, relf_sym->name) != 0)) { ++ continue; + } ++ return uelf_sym; + } + +- uelf_sym = file_sym; +- list_for_each_entry_continue(uelf_sym, &uelf->symbols, list) { +- if (uelf_sym->type == STT_FILE) { ++ return NULL; ++} ++ ++static struct debug_symbol* match_relf_local_symbol(struct running_elf *relf, ++ int start_index, struct symbol *uelf_sym) ++{ ++ for (int i = start_index + 1; i < relf->obj_nr; i++) { ++ struct debug_symbol *relf_sym = &relf->obj_syms[i]; ++ ++ if (relf_sym->type == STT_FILE) { + break; // find until next file + } +- if (uelf_sym->bind != STB_LOCAL) { ++ if (relf_sym->bind != STB_LOCAL) { + continue; + } +- if ((relf_sym->type != STT_FUNC) && +- (relf_sym->type != STT_OBJECT)) { ++ if ((relf_sym->type != STT_FUNC) && (relf_sym->type != STT_OBJECT)) { + continue; + } +- if (discarded_sym(relf, uelf_sym)) { ++ if ((relf_sym->type != uelf_sym->type) || ++ (strcmp(relf_sym->name, uelf_sym->name) != 0)) { + continue; + } +- +- found = NOT_FOUND; +- for (int i = file_sym_idx + 1; i < relf->obj_nr; i++) { +- relf_sym = &relf->obj_syms[i]; +- +- if (relf_sym->type == STT_FILE) { +- break; // find until next file +- } +- if (relf_sym->bind != STB_LOCAL) { +- continue; +- } +- if ((uelf_sym->type == relf_sym->type) && +- (strcmp(uelf_sym->name, relf_sym->name) == 0)) { +- found = FOUND; +- break; +- } +- } +- +- if (found == NOT_FOUND) { +- log_warn("Cannot find symbol '%s' in %s\n", +- uelf_sym->name, g_uelf_name); +- return NOT_FOUND; +- } ++ return relf_sym; + } + +- return found; ++ return NULL; + } + +-static void find_local_syms(struct upatch_elf *uelf, struct running_elf *relf, +- struct symbol *file_sym) ++static void match_file_local_symbols( ++ struct upatch_elf *uelf, struct running_elf *relf, ++ struct symbol *uelf_filesym, int relf_fileidx) + { +- struct debug_symbol *relf_sym = NULL; +- struct debug_symbol *found_sym = NULL; +- enum local_match found; ++ for (int i = relf_fileidx + 1; i < relf->obj_nr; i++) { ++ struct debug_symbol *sym = &relf->obj_syms[i]; + +- for (int i = 0; i < relf->obj_nr; i++) { +- relf_sym = &relf->obj_syms[i]; ++ if (sym->type == STT_FILE) { ++ break; // match within current file ++ } ++ if ((sym->bind != STB_LOCAL) || ++ ((sym->type != STT_FUNC) && (sym->type != STT_OBJECT))) { ++ continue; ++ } + +- if (relf_sym->type != STT_FILE) { ++ struct symbol *matched = match_uelf_local_symbol(uelf, uelf_filesym, sym); ++ if (matched == NULL) { ++ ERROR("Cannot find symbol '%s' in %s", sym->name, g_uelf_name); ++ } ++ } ++ ++ struct symbol *sym = uelf_filesym; ++ list_for_each_entry_continue(sym, &uelf->symbols, list) { ++ if (sym->type == STT_FILE) { ++ break; // match within current file ++ } ++ if ((sym->bind != STB_LOCAL) || ++ ((sym->type != STT_FUNC) && (sym->type != STT_OBJECT))) { + continue; + } +- if (strcmp(file_sym->name, relf_sym->name)) { ++ if (is_discarded_sym(relf, sym)) { + continue; + } + +- found = locals_match(uelf, relf, file_sym, i); +- if (found == NOT_FOUND) { +- continue; +- } else if (found == EMPTY) { +- found_sym = relf_sym; +- break; +- } else { +- if (found_sym) { +- ERROR("Found duplicate local symbols in '%s'", g_relf_name); +- } +- found_sym = relf_sym; ++ struct debug_symbol *matched = match_relf_local_symbol(relf, relf_fileidx, sym); ++ if (matched == NULL) { ++ ERROR("Cannot find symbol '%s' in %s", sym->name, g_relf_name); ++ } ++ if ((sym->debug_sym != NULL) && (sym->debug_sym != matched)) { ++ ERROR("Found duplicated symbol '%s' in %s", sym->name, g_relf_name); + } ++ sym->debug_sym = matched; + } ++} + +- if (!found_sym) { +- ERROR("Cannot find local symbol in '%s'", g_relf_name); +- } ++static bool find_debug_file_symbol(struct running_elf *relf, ++ struct symbol *file_sym, int *index) ++{ ++ for (int i = 0; i < relf->obj_nr; i++) { ++ struct debug_symbol *debug_sym = &relf->obj_syms[i]; + +- list_for_each_entry_continue(file_sym, &uelf->symbols, list) { +- if (file_sym->type == STT_FILE) { +- break; ++ if (debug_sym->type != STT_FILE) { ++ continue; ++ } ++ if (strcmp(file_sym->name, debug_sym->name) == 0) { ++ *index = i; ++ return true; + } +- file_sym->relf_sym = found_sym; + } ++ return false; + } + + /* +@@ -492,15 +467,19 @@ static void find_local_syms(struct upatch_elf *uelf, struct running_elf *relf, + * We then compare local symbol lists from both blocks and store the pointer + * to STT_FILE symbol in running elf for later using. + */ +-static void find_debug_symbol(struct upatch_elf *uelf, struct running_elf *relf) ++static void match_local_symbols(struct upatch_elf *uelf, struct running_elf *relf) + { +- struct symbol *file_sym = NULL; ++ struct symbol *uelf_filesym = NULL; + +- list_for_each_entry(file_sym, &uelf->symbols, list) { +- if ((file_sym->type == STT_FILE) && (file_sym->status == CHANGED)) { +- log_debug("file '%s' is CHANGED\n", file_sym->name); +- find_local_syms(uelf, relf, file_sym); ++ list_for_each_entry(uelf_filesym, &uelf->symbols, list) { ++ if ((uelf_filesym->type != STT_FILE) || (uelf_filesym->status != CHANGED)) { ++ continue; ++ } ++ int relf_fileidx = 0; ++ if (!find_debug_file_symbol(relf, uelf_filesym, &relf_fileidx)) { ++ ERROR("Cannot find file '%s' in %s", uelf_filesym->name, g_relf_name); + } ++ match_file_local_symbols(uelf, relf, uelf_filesym, relf_fileidx); + } + } + +@@ -1039,7 +1018,7 @@ int main(int argc, char*argv[]) + + upatch_compare_correlated_elements(&uelf_patched); + mark_file_symbols(&uelf_source); +- find_debug_symbol(&uelf_source, &relf); ++ match_local_symbols(&uelf_source, &relf); + + include_standard_elements(&uelf_patched); + +diff --git a/upatch-diff/elf-correlate.c b/upatch-diff/elf-correlate.c +index 59069a3..9738784 100644 +--- a/upatch-diff/elf-correlate.c ++++ b/upatch-diff/elf-correlate.c +@@ -42,8 +42,8 @@ static void correlate_symbol(struct symbol *sym_orig, + sym_patched->name = sym_orig->name; + sym_patched->name_source = DATA_SOURCE_REF; + } +- if (sym_orig->relf_sym && !sym_patched->relf_sym) { +- sym_patched->relf_sym = sym_orig->relf_sym; ++ if (sym_orig->debug_sym && !sym_patched->debug_sym) { ++ sym_patched->debug_sym = sym_orig->debug_sym; + } + } + +diff --git a/upatch-diff/upatch-elf.h b/upatch-diff/upatch-elf.h +index 653439e..df5111a 100644 +--- a/upatch-diff/upatch-elf.h ++++ b/upatch-diff/upatch-elf.h +@@ -112,7 +112,7 @@ struct symbol { + GElf_Sym sym; + char *name; + enum data_source name_source; +- struct debug_symbol *relf_sym; ++ struct debug_symbol *debug_sym; + unsigned int index; + unsigned char bind; + unsigned char type; +-- +2.43.0 + diff --git a/0076-upatch-diff-skip-local-symbols-like-__func__.xxx.patch b/0076-upatch-diff-skip-local-symbols-like-__func__.xxx.patch new file mode 100644 index 0000000000000000000000000000000000000000..a308dd1ab18fe0f6d1e5a824061b31f710b8fc35 --- /dev/null +++ b/0076-upatch-diff-skip-local-symbols-like-__func__.xxx.patch @@ -0,0 +1,62 @@ +From 63ac3788d9a24edaeda90eaa9c1a71caf9f0c3b3 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Tue, 29 Apr 2025 21:03:27 +0800 +Subject: [PATCH] upatch-diff: skip local symbols like __func__.xxx + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 3d6edc8..96fcbd4 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -348,6 +348,24 @@ static bool is_discarded_sym(struct running_elf *relf, struct symbol *sym) + return false; + } + ++static bool has_function_prefix(const char *sym_name) ++{ ++ static const char *SYM_NAMES[] = { ++ "__func__.", ++ "__FUNC__.", ++ "__PRETTY_FUNCTION__.", ++ NULL, ++ }; ++ ++ const char **name; ++ for (name = SYM_NAMES; *name; name++) { ++ if (strcmp(sym_name, *name) == 0) { ++ return true; ++ } ++ } ++ return false; ++} ++ + static struct symbol* match_uelf_local_symbol(struct upatch_elf *uelf, + struct symbol *start_sym, struct debug_symbol *relf_sym) + { +@@ -411,6 +429,9 @@ static void match_file_local_symbols( + ((sym->type != STT_FUNC) && (sym->type != STT_OBJECT))) { + continue; + } ++ if (has_function_prefix(sym->name)) { ++ continue; ++ } + + struct symbol *matched = match_uelf_local_symbol(uelf, uelf_filesym, sym); + if (matched == NULL) { +@@ -427,6 +448,9 @@ static void match_file_local_symbols( + ((sym->type != STT_FUNC) && (sym->type != STT_OBJECT))) { + continue; + } ++ if (has_function_prefix(sym->name)) { ++ continue; ++ } + if (is_discarded_sym(relf, sym)) { + continue; + } +-- +2.43.0 + diff --git a/0077-upatch-diff-warning-on-no-function-changed-when-crea.patch b/0077-upatch-diff-warning-on-no-function-changed-when-crea.patch new file mode 100644 index 0000000000000000000000000000000000000000..e9b147291bd4f764524b4f8c19434925067f1adb --- /dev/null +++ b/0077-upatch-diff-warning-on-no-function-changed-when-crea.patch @@ -0,0 +1,30 @@ +From e206547f6b1570054f7aec8594fd3c7bd997b247 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 7 May 2025 10:41:06 +0800 +Subject: [PATCH] upatch-diff: warning on no function changed when creating + patch + +Signed-off-by: renoseven +--- + upatch-diff/elf-create.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/upatch-diff/elf-create.c b/upatch-diff/elf-create.c +index 139f92d..63dbdb2 100644 +--- a/upatch-diff/elf-create.c ++++ b/upatch-diff/elf-create.c +@@ -161,6 +161,11 @@ void upatch_create_patches_sections(struct upatch_elf *uelf, + nr++; + } + ++ if (nr == 0) { ++ log_warn("No functional changes\n"); ++ return; ++ } ++ + /* create text/rela section pair */ + sec = create_section_pair(uelf, ".upatch.funcs", sizeof(*funcs), nr); + relasec = sec->rela; +-- +2.43.0 + diff --git a/0078-upatch-diff-treat-.L-symbol-as-special-symbol.patch b/0078-upatch-diff-treat-.L-symbol-as-special-symbol.patch new file mode 100644 index 0000000000000000000000000000000000000000..38acccc64473dbf7d8736c7ff0c4747b66addecf --- /dev/null +++ b/0078-upatch-diff-treat-.L-symbol-as-special-symbol.patch @@ -0,0 +1,37 @@ +From 6956275e7e1298df7bf99355afdb111453295972 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 7 May 2025 10:55:42 +0800 +Subject: [PATCH] upatch-diff: treat .L symbol as special symbol + +Signed-off-by: renoseven +--- + upatch-diff/elf-common.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/upatch-diff/elf-common.c b/upatch-diff/elf-common.c +index 6e13c34..0ac8188 100644 +--- a/upatch-diff/elf-common.c ++++ b/upatch-diff/elf-common.c +@@ -59,6 +59,7 @@ bool is_special_static_symbol(struct symbol *sym) + ".CSWTCH", + "._entry", + ".C", ++ ".L", + NULL, + }; + +@@ -153,11 +154,6 @@ bool is_normal_static_local(struct symbol *sym) + if (sym->type != STT_OBJECT || sym->bind != STB_LOCAL) { + return false; + } +- // TODO: .Local ? need a example here +- if (!strncmp(sym->name, ".L", 2)) { +- ERROR("find no-local variable\n"); +- return false; +- } + if (!strchr(sym->name, '.')) { + return false; + } +-- +2.43.0 + diff --git a/0079-upatch-diff-allow-object-symbol-size-changes.patch b/0079-upatch-diff-allow-object-symbol-size-changes.patch new file mode 100644 index 0000000000000000000000000000000000000000..f4a9fe5ae5f5b4a838eef983f0a249fcb0dc65ca --- /dev/null +++ b/0079-upatch-diff-allow-object-symbol-size-changes.patch @@ -0,0 +1,28 @@ +From a4491cbb9ecf111891e9ca443d43184d9497ea5c Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 7 May 2025 11:02:31 +0800 +Subject: [PATCH] upatch-diff: allow object symbol size changes + +Signed-off-by: renoseven +--- + upatch-diff/elf-compare.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c +index 7314a27..9aa92bf 100644 +--- a/upatch-diff/elf-compare.c ++++ b/upatch-diff/elf-compare.c +@@ -40,10 +40,6 @@ static void compare_correlated_symbol(struct symbol *sym, struct symbol *twin) + if (sym->sym.st_info != twin->sym.st_info) { + ERROR("Symbol '%s' st_info mismatched", sym->name); + } +- // object symbol size cannot be changed +- if ((sym->type == STT_OBJECT) && (sym->sym.st_size != twin->sym.st_size)) { +- ERROR("Symbol '%s' object size mismatched", sym->name); +- } + + /* + * For local symbols, we handle them based on their matching sections. +-- +2.43.0 + diff --git a/0080-upatch-diff-optimize-log.patch b/0080-upatch-diff-optimize-log.patch new file mode 100644 index 0000000000000000000000000000000000000000..6adeed78c9e8540ff91820cddc65b8f03153707f --- /dev/null +++ b/0080-upatch-diff-optimize-log.patch @@ -0,0 +1,59 @@ +From 2216b99f6c74af08c41ab7858931da59cf62f128 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 8 May 2025 14:37:17 +0800 +Subject: [PATCH] upatch-diff: optimize log + +Signed-off-by: renoseven +--- + upatch-diff/log.h | 27 +++++++++++++-------------- + 1 file changed, 13 insertions(+), 14 deletions(-) + +diff --git a/upatch-diff/log.h b/upatch-diff/log.h +index a109958..b91ae9a 100644 +--- a/upatch-diff/log.h ++++ b/upatch-diff/log.h +@@ -32,15 +32,16 @@ + extern enum log_level g_loglevel; + extern char *g_logprefix; + +-enum exit_status { +- EXIT_STATUS_SUCCESS = 0, +- EXIT_STATUS_ERROR = 1, +-}; +- + /* Since upatch-build is an one-shot program, we do not care about failure handler */ +-#define ERROR(format, ...) \ +- error(EXIT_STATUS_ERROR, 0, "ERROR: %s: %s: %d: " format, \ +- g_logprefix, __FUNCTION__, __LINE__, ##__VA_ARGS__) ++#define ERROR(format, ...) do { \ ++ if (g_logprefix) { \ ++ error(EXIT_FAILURE, 0, "ERROR: %s: %s:%d: " format, \ ++ g_logprefix, __func__, __LINE__, ##__VA_ARGS__); \ ++ } else { \ ++ error(EXIT_FAILURE, 0, "ERROR: %s:%d: " format, \ ++ __func__, __LINE__, ##__VA_ARGS__); \ ++ } \ ++} while (0) + + /* it is time cost */ + #define log_debug(format, ...) log(DEBUG, format, ##__VA_ARGS__) +@@ -48,12 +49,10 @@ enum exit_status { + #define log_warn(format, ...) log(WARN, format, ##__VA_ARGS__) + #define log_error(format, ...) log(ERR, format, ##__VA_ARGS__) + +-#define log(level, format, ...) \ +- do { \ +- if (g_loglevel <= (level)) { \ +- printf(format, ##__VA_ARGS__); \ +- } \ +- } while (0) ++#define log(level, format, ...) do { \ ++ if (g_loglevel > (level)) { break; } \ ++ fprintf((level <= NORMAL) ? stdout : stderr, format, ##__VA_ARGS__); \ ++} while (0) + + #define REQUIRE(COND, message) \ + do { \ +-- +2.43.0 + diff --git a/0081-upatch-diff-enrich-error-message.patch b/0081-upatch-diff-enrich-error-message.patch new file mode 100644 index 0000000000000000000000000000000000000000..aab9e7014f6e79d92bef22764a7b6bf1e960ab78 --- /dev/null +++ b/0081-upatch-diff-enrich-error-message.patch @@ -0,0 +1,55 @@ +From 7a69921495c2e6d0f65d6d34abde0f8964355f87 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 8 May 2025 14:37:32 +0800 +Subject: [PATCH] upatch-diff: enrich error message + +Signed-off-by: renoseven +--- + upatch-diff/upatch-elf.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/upatch-diff/upatch-elf.c b/upatch-diff/upatch-elf.c +index a51f008..ea09e54 100644 +--- a/upatch-diff/upatch-elf.c ++++ b/upatch-diff/upatch-elf.c +@@ -333,12 +333,12 @@ void upatch_elf_open(struct upatch_elf *uelf, const char *name) + + fd = open(name, O_RDONLY); + if (fd == -1) { +- ERROR("open %s failed with errno %d\n", name, errno); ++ ERROR("Failed to open '%s', %s", name, strerror(errno)); + } + + elf = elf_begin(fd, ELF_C_RDWR, NULL); + if (!elf) { +- ERROR("open elf %s failed with error %s\n", name, elf_errmsg(0)); ++ ERROR("Failed to parse elf, %s", elf_errmsg(0)); + } + + memset(uelf, 0, sizeof(*uelf)); +@@ -350,11 +350,10 @@ void upatch_elf_open(struct upatch_elf *uelf, const char *name) + uelf->fd = fd; + + if (!gelf_getehdr(uelf->elf, &ehdr)) { +- ERROR("get file %s elf header failed with error %s\n", name, +- elf_errmsg(0)); ++ ERROR("Failed to read elf header, %s", elf_errmsg(0)); + } + if (ehdr.e_type != ET_REL) { +- ERROR("only handles relocatable files\n"); ++ ERROR("File is not an object"); + } + + /* +@@ -369,7 +368,7 @@ void upatch_elf_open(struct upatch_elf *uelf, const char *name) + uelf->arch = X86_64; + break; + default: +- ERROR("unsupported architecture here"); ++ ERROR("Unsupported architecture"); + } + + create_section_list(uelf); +-- +2.43.0 + diff --git a/0082-upatch-diff-improve-initializing-object-handling.patch b/0082-upatch-diff-improve-initializing-object-handling.patch new file mode 100644 index 0000000000000000000000000000000000000000..bc54d11a706c1f747f76d8faa5553b1d818628d0 --- /dev/null +++ b/0082-upatch-diff-improve-initializing-object-handling.patch @@ -0,0 +1,548 @@ +From 79930859794b188c16c16e35798ae037e4b415c3 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 8 May 2025 18:53:52 +0800 +Subject: [PATCH] upatch-diff: improve initializing & object handling + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 179 +++++++++++++------------------ + upatch-diff/running-elf.c | 72 ++++++------- + upatch-diff/running-elf.h | 5 +- + upatch-diff/upatch-elf.c | 53 ++++----- + upatch-diff/upatch-elf.h | 9 +- + 5 files changed, 141 insertions(+), 177 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 96fcbd4..9973ee0 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -57,7 +57,6 @@ + #include "elf-resolve.h" + #include "elf-create.h" + #include "running-elf.h" +-//#include "upatch-manage.h" + #include "upatch-patch.h" + + #define PROG_VERSION "upatch-diff "BUILD_VERSION +@@ -75,37 +74,17 @@ struct arguments { + bool debug; + }; + +-static struct argp_option options[] = { +- {"debug", 'd', NULL, 0, "Show debug output", 0}, +- {"source", 's', "source", 0, "Source object", 0}, +- {"patched", 'p', "patched", 0, "Patched object", 0}, +- {"running", 'r', "running", 0, "Running binary file", 0}, +- {"output", 'o', "output", 0, "Output object", 0}, ++static const struct argp_option ARGP_OPTION[] = { ++ {"source", 's', "", 0, "Source object", 0}, ++ {"patched", 'p', "", 0, "Patched object", 1}, ++ {"running", 'r', "", 0, "Running binary file", 2}, ++ {"output", 'o', "", 0, "Output object", 3}, ++ {"debug", 'd', NULL, 0, "Show debug output", 4}, + {NULL} + }; +- +-static char program_doc[] = +- "upatch-build -- generate a patch object based on the source object"; +- +-static char args_doc[] = +- "-s source_obj -p patched_obj -r elf_file -o output_obj"; +- ++static const char ARGP_DOC[] = "Generate a patch object based on source object"; + const char *argp_program_version = PROG_VERSION; + +-static error_t check_opt(struct argp_state *state) +-{ +- struct arguments *arguments = state->input; +- +- if (arguments->source_obj == NULL || +- arguments->patched_obj == NULL || +- arguments->running_elf == NULL || +- arguments->output_obj == NULL) { +- argp_usage(state); +- return ARGP_ERR_UNKNOWN; +- } +- return 0; +-} +- + static error_t parse_opt(int key, char *arg, struct argp_state *state) + { + struct arguments *arguments = state->input; +@@ -126,35 +105,43 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) + case 'o': + arguments->output_obj = arg; + break; +- case ARGP_KEY_ARG: +- break; +- case ARGP_KEY_END: +- return check_opt(state); + default: + return ARGP_ERR_UNKNOWN; + } + return 0; + } + +-static struct argp argp = { +- options, parse_opt, args_doc, program_doc, NULL, NULL, NULL +-}; +- +-/* +- * Key point for chreate-diff-object: +- * 1. find changed func/data for each object +- * 2. link all these objects into a relocatable file +- * 3. add sections for management (hash/init/patch info etc.) +- * 4. locate old symbols for the relocatable file +- */ ++static bool check_args(struct arguments *arguments) ++{ ++ if (arguments->source_obj == NULL) { ++ log_error("The argument '--source ' requires a value\n"); ++ return false; ++ } ++ if (arguments->patched_obj == NULL) { ++ log_error("The argument '--patched ' requires a value\n"); ++ return false; ++ } ++ if (arguments->running_elf == NULL) { ++ log_error("The argument '--running ' requires a value\n"); ++ return false; ++ } ++ if (arguments->output_obj == NULL) { ++ log_error("The argument '--output ' requires a value\n"); ++ return false; ++ } ++ return true; ++} + +-/* Format of output file is the only export API */ + static void show_program_info(struct arguments *arguments) + { +- log_debug("source object: %s\n", arguments->source_obj); ++ log_debug("==============================\n"); ++ log_debug("%s\n", PROG_VERSION); ++ log_debug("==============================\n"); ++ log_debug("source object: %s\n", arguments->source_obj); + log_debug("patched object: %s\n", arguments->patched_obj); + log_debug("running binary: %s\n", arguments->running_elf); +- log_debug("output object: %s\n", arguments->output_obj); ++ log_debug("output object: %s\n", arguments->output_obj); ++ log_debug("------------------------------\n\n"); + } + + static void compare_elf_headers(struct upatch_elf *uelf_source, +@@ -182,19 +169,6 @@ static void compare_elf_headers(struct upatch_elf *uelf_source, + } + } + +-/* we can sure we only handle relocatable file, this is unnecessary */ +-static void check_program_headers(struct upatch_elf *uelf) +-{ +- size_t ph_nr; +- +- if (elf_getphdrnum(uelf->elf, &ph_nr)) { +- ERROR("elf_getphdrnum with error %s.", elf_errmsg(0)); +- } +- if (ph_nr != 0) { +- ERROR("ELF contains program header."); +- } +-} +- + static char *strarrcmp(char *name, char **prefix) + { + size_t len; +@@ -948,7 +922,6 @@ static void migrate_included_elements(struct upatch_elf *uelf_patched, + struct symbol *sym; + struct symbol *safesym; + +- memset(uelf_out, 0, sizeof(struct upatch_elf)); + uelf_out->arch = uelf_patched->arch; + + INIT_LIST_HEAD(&uelf_out->sections); +@@ -988,40 +961,48 @@ static void migrate_included_elements(struct upatch_elf *uelf_patched, + } + } + +-int main(int argc, char*argv[]) ++/* ++ * Key point for upatch-diff: ++ * 1. find changed func/data for each object ++ * 2. link all these objects into a relocatable file ++ * 3. add sections for management (hash/init/patch info etc.) ++ * 4. locate old symbols for the relocatable file ++ */ ++int main(int argc, char **argv) + { +- struct arguments arguments; +- struct upatch_elf uelf_source; +- struct upatch_elf uelf_patched; +- struct upatch_elf uelf_out; +- struct running_elf relf; +- +- memset(&arguments, 0, sizeof(arguments)); +- argp_parse(&argp, argc, argv, 0, NULL, &arguments); +- +- if (arguments.debug) { ++ static const struct argp ARGP = { ++ ARGP_OPTION, parse_opt, NULL, ARGP_DOC, NULL, NULL, NULL ++ }; ++ struct arguments args = { 0 }; ++ struct upatch_elf uelf_source = { 0 }; ++ struct upatch_elf uelf_patched = { 0 }; ++ struct upatch_elf uelf_out = { 0 }; ++ struct running_elf relf = { 0 }; ++ ++ if (argp_parse(&ARGP, argc, argv, 0, NULL, &args) != 0) { ++ return EXIT_FAILURE; ++ } ++ if (!check_args(&args)) { ++ return EXIT_FAILURE; ++ } ++ if (args.debug) { + g_loglevel = DEBUG; + } +- g_logprefix = basename(arguments.source_obj); +- show_program_info(&arguments); ++ show_program_info(&args); + + if (elf_version(EV_CURRENT) == EV_NONE) { +- ERROR("ELF library initialization failed"); ++ log_error("Failed to initialize elf library\n"); ++ return EXIT_FAILURE; + } + +- /* TODO: with debug info, this may changed */ +- g_uelf_name = arguments.source_obj; +- g_relf_name = arguments.running_elf; +- +- /* check error in log, since errno may be from libelf */ +- upatch_elf_open(&uelf_source, arguments.source_obj); +- upatch_elf_open(&uelf_patched, arguments.patched_obj); +- +- relf_init(arguments.running_elf, &relf); ++ uelf_open(&uelf_source, args.source_obj); ++ uelf_open(&uelf_patched, args.patched_obj); ++ relf_open(&relf, args.running_elf); + ++ g_logprefix = basename(args.source_obj); ++ g_uelf_name = args.source_obj; ++ g_relf_name = args.running_elf; + compare_elf_headers(&uelf_source, &uelf_patched); +- check_program_headers(&uelf_source); +- check_program_headers(&uelf_patched); + + bundle_symbols(&uelf_source); + bundle_symbols(&uelf_patched); +@@ -1031,7 +1012,6 @@ int main(int argc, char*argv[]) + + mark_ignored_sections(&uelf_source); + mark_ignored_sections(&uelf_patched); +- + mark_grouped_sections(&uelf_patched); + + replace_section_syms(&uelf_source); +@@ -1049,12 +1029,8 @@ int main(int argc, char*argv[]) + int change_count = include_changes(&uelf_patched); + if (change_count == 0) { + log_normal("No functional changes\n"); +- upatch_elf_destroy(&uelf_source); +- upatch_elf_destroy(&uelf_patched); +- +- upatch_elf_close(&uelf_source); +- upatch_elf_close(&uelf_patched); +- ++ uelf_close(&uelf_source); ++ uelf_close(&uelf_patched); + relf_close(&relf); + return 0; + } +@@ -1103,22 +1079,15 @@ int main(int argc, char*argv[]) + + upatch_dump_kelf(&uelf_out); + +- upatch_write_output_elf(&uelf_out, uelf_patched.elf, arguments.output_obj, +- 0664); +- +- upatch_elf_destroy(&uelf_source); +- upatch_elf_destroy(&uelf_patched); +- upatch_elf_destroy(&uelf_out); +- +- upatch_elf_close(&uelf_source); +- upatch_elf_close(&uelf_patched); +- upatch_elf_close(&uelf_out); ++ upatch_write_output_elf(&uelf_out, uelf_patched.elf, args.output_obj, 0664); ++ log_normal("Done\n"); + ++ uelf_close(&uelf_source); ++ uelf_close(&uelf_patched); ++ uelf_close(&uelf_out); + relf_close(&relf); + +- log_normal("Done\n"); + fflush(stdout); + fflush(stderr); +- +- return 0; ++ return EXIT_SUCCESS; + } +diff --git a/upatch-diff/running-elf.c b/upatch-diff/running-elf.c +index b4d6d24..f984a26 100644 +--- a/upatch-diff/running-elf.c ++++ b/upatch-diff/running-elf.c +@@ -35,72 +35,63 @@ + #include "running-elf.h" + #include "log.h" + +-/* TODO: +- * need to judge whether running_elf is a Position-Independent Executable file +- * https://github.com/bminor/binutils-gdb/blob/master/binutils/readelf.c +- */ +-static bool is_pie(void) +-{ +- return true; +-} +- +-static bool is_exec(struct Elf *elf) ++void relf_open(struct running_elf *relf, const char *name) + { + GElf_Ehdr ehdr; +- +- if (!gelf_getehdr(elf, &ehdr)) { +- ERROR("gelf_getehdr running_file failed for %s.", elf_errmsg(0)); +- } +- return ehdr.e_type == ET_EXEC || (ehdr.e_type == ET_DYN && is_pie()); +-} +- +-void relf_init(char *elf_name, struct running_elf *relf) +-{ + GElf_Shdr shdr; +- Elf_Scn *scn = NULL; +- Elf_Data *data; + GElf_Sym sym; + +- relf->fd = open(elf_name, O_RDONLY); ++ if (relf == NULL) { ++ return; ++ } ++ ++ relf->fd = open(name, O_RDONLY); + if (relf->fd == -1) { +- ERROR("open with errno = %d", errno); ++ ERROR("Failed to open '%s', %s", name, strerror(errno)); + } + + relf->elf = elf_begin(relf->fd, ELF_C_READ, NULL); + if (!relf->elf) { +- ERROR("elf_begin with error %s", elf_errmsg(0)); ++ ERROR("Failed to read file '%s', %s", name, elf_errmsg(0)); + } + +- relf->is_exec = is_exec(relf->elf); ++ if (!gelf_getehdr(relf->elf, &ehdr)) { ++ ERROR("Failed to read file '%s' elf header, %s", name, elf_errmsg(0)); ++ } ++ relf->is_exec = ((ehdr.e_type == ET_EXEC) || (ehdr.e_type == ET_DYN)); + ++ Elf_Scn *scn = NULL; + while ((scn = elf_nextscn(relf->elf, scn)) != NULL) { + if (!gelf_getshdr(scn, &shdr)) { +- ERROR("gelf_getshdr with error %s", elf_errmsg(0)); ++ ERROR("Failed to read file '%s' section header, %s", ++ name, elf_errmsg(0)); + } + if (shdr.sh_type == SHT_SYMTAB) { + break; + } + } + +- data = elf_getdata(scn, NULL); ++ Elf_Data *data = elf_getdata(scn, NULL); + if (!data) { +- ERROR("elf_getdata with error %s", elf_errmsg(0)); ++ ERROR("Failed to read file '%s' section data, %s", name, elf_errmsg(0)); + } + + relf->obj_nr = (int)(shdr.sh_size / shdr.sh_entsize); + relf->obj_syms = calloc((size_t)relf->obj_nr, sizeof(struct debug_symbol)); + if (!relf->obj_syms) { +- ERROR("calloc with errno = %d", errno); ++ ERROR("Failed to alloc memory, %s", strerror(errno)); + } + + for (int i = 0; i < relf->obj_nr; i++) { + if (!gelf_getsym(data, i, &sym)) { +- ERROR("gelf_getsym with error %s", elf_errmsg(0)); ++ ERROR("Failed to read file '%s' symbol, index=%d, %s", ++ name, i, elf_errmsg(0)); + } + relf->obj_syms[i].name = elf_strptr(relf->elf, + shdr.sh_link, sym.st_name); + if (!relf->obj_syms[i].name) { +- ERROR("elf_strptr with error %s", elf_errmsg(0)); ++ ERROR("Failed to read file '%s' symbol name, index=%d, %s", ++ name, i, elf_errmsg(0)); + } + relf->obj_syms[i].type = GELF_ST_TYPE(sym.st_info); + relf->obj_syms[i].bind = GELF_ST_BIND(sym.st_info); +@@ -110,15 +101,22 @@ void relf_init(char *elf_name, struct running_elf *relf) + } + } + +-int relf_close(struct running_elf *relf) ++void relf_close(struct running_elf *relf) + { +- free(relf->obj_syms); +- elf_end(relf->elf); ++ if (relf == NULL) { ++ return; ++ } ++ if (relf->obj_syms) { ++ free(relf->obj_syms); ++ } ++ if (relf->elf) { ++ elf_end(relf->elf); ++ } ++ if (relf->fd > 0) { ++ close(relf->fd); ++ } + relf->elf = NULL; +- close(relf->fd); + relf->fd = -1; +- +- return 0; + } + + bool lookup_relf(struct running_elf *relf, struct symbol *lookup_sym, +diff --git a/upatch-diff/running-elf.h b/upatch-diff/running-elf.h +index cdf61d1..23dd9c1 100644 +--- a/upatch-diff/running-elf.h ++++ b/upatch-diff/running-elf.h +@@ -56,9 +56,8 @@ struct running_elf { + bool is_exec; + }; + +-void relf_init(char *, struct running_elf *); +- +-int relf_close(struct running_elf *); ++void relf_open(struct running_elf *relf, const char *name); ++void relf_close(struct running_elf *relf); + + bool lookup_relf(struct running_elf *, struct symbol *, struct lookup_result *); + +diff --git a/upatch-diff/upatch-elf.c b/upatch-diff/upatch-elf.c +index ea09e54..2f88a92 100644 +--- a/upatch-diff/upatch-elf.c ++++ b/upatch-diff/upatch-elf.c +@@ -322,38 +322,34 @@ static void destroy_string_list(struct upatch_elf *uelf) + INIT_LIST_HEAD(&uelf->strings); + } + +-void upatch_elf_open(struct upatch_elf *uelf, const char *name) ++void uelf_open(struct upatch_elf *uelf, const char *name) + { +- int fd = 1; +- +- Elf *elf = NULL; +- + GElf_Ehdr ehdr; +- struct section *sec; + +- fd = open(name, O_RDONLY); ++ if (uelf == NULL) { ++ return; ++ } ++ INIT_LIST_HEAD(&uelf->sections); ++ INIT_LIST_HEAD(&uelf->symbols); ++ INIT_LIST_HEAD(&uelf->strings); ++ ++ int fd = open(name, O_RDONLY); + if (fd == -1) { + ERROR("Failed to open '%s', %s", name, strerror(errno)); + } ++ uelf->fd = fd; + +- elf = elf_begin(fd, ELF_C_RDWR, NULL); ++ Elf *elf = elf_begin(fd, ELF_C_READ, NULL); + if (!elf) { +- ERROR("Failed to parse elf, %s", elf_errmsg(0)); ++ ERROR("Failed to read file '%s', %s", name, elf_errmsg(0)); + } +- +- memset(uelf, 0, sizeof(*uelf)); +- INIT_LIST_HEAD(&uelf->sections); +- INIT_LIST_HEAD(&uelf->symbols); +- INIT_LIST_HEAD(&uelf->strings); +- + uelf->elf = elf; +- uelf->fd = fd; + + if (!gelf_getehdr(uelf->elf, &ehdr)) { +- ERROR("Failed to read elf header, %s", elf_errmsg(0)); ++ ERROR("Failed to read file '%s' elf header, %s", name, elf_errmsg(0)); + } + if (ehdr.e_type != ET_REL) { +- ERROR("File is not an object"); ++ ERROR("File '%s' is not object file", name); + } + + /* +@@ -374,6 +370,7 @@ void upatch_elf_open(struct upatch_elf *uelf, const char *name) + create_section_list(uelf); + create_symbol_list(uelf); + ++ struct section *sec; + list_for_each_entry(sec, &uelf->sections, list) { + if (is_rela_section(sec)) { + create_rela_list(uelf, sec); +@@ -381,16 +378,22 @@ void upatch_elf_open(struct upatch_elf *uelf, const char *name) + } + } + +-void upatch_elf_destroy(struct upatch_elf *uelf) ++void uelf_close(struct upatch_elf *uelf) + { ++ if (uelf == NULL) { ++ return; ++ } + destroy_section_list(uelf); + destroy_symbol_list(uelf); + destroy_string_list(uelf); +-} + +-void upatch_elf_close(struct upatch_elf *uelf) +-{ +- elf_end(uelf->elf); +- close(uelf->fd); +- memset(uelf, 0, sizeof(*uelf)); ++ if (uelf->elf) { ++ elf_end(uelf->elf); ++ } ++ if (uelf->fd > 0) { ++ close(uelf->fd); ++ } ++ uelf->elf = NULL; ++ uelf->fd = -1; ++ uelf->symtab_shndx = NULL; + } +diff --git a/upatch-diff/upatch-elf.h b/upatch-diff/upatch-elf.h +index df5111a..d8af728 100644 +--- a/upatch-diff/upatch-elf.h ++++ b/upatch-diff/upatch-elf.h +@@ -138,12 +138,7 @@ struct upatch_elf { + int fd; + }; + +-// init a upatch_elf from a path +-void upatch_elf_open(struct upatch_elf *, const char *); +- +-// Destory upatch_elf struct +-void upatch_elf_destroy(struct upatch_elf *); +- +-void upatch_elf_close(struct upatch_elf *); ++void uelf_open(struct upatch_elf *uelf, const char *name); ++void uelf_close(struct upatch_elf *uelf); + + #endif +-- +2.43.0 + diff --git a/0083-upatch-diff-fix-uelf-list-insert-order-issue.patch b/0083-upatch-diff-fix-uelf-list-insert-order-issue.patch new file mode 100644 index 0000000000000000000000000000000000000000..56483b2aa9f0f6004e7e71e31b5f30b6fbc211b7 --- /dev/null +++ b/0083-upatch-diff-fix-uelf-list-insert-order-issue.patch @@ -0,0 +1,26 @@ +From 9248663d9a1c866abc9222dc671b4f3f9bb2607f Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 9 May 2025 15:15:08 +0800 +Subject: [PATCH] upatch-diff: fix uelf list insert order issue + +Signed-off-by: renoseven +--- + upatch-diff/elf-common.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/upatch-diff/elf-common.h b/upatch-diff/elf-common.h +index 672295c..01a1152 100644 +--- a/upatch-diff/elf-common.h ++++ b/upatch-diff/elf-common.h +@@ -45,7 +45,7 @@ + } \ + INIT_LIST_HEAD(&(_new)->list); \ + if (_list) { \ +- list_add(&(_new)->list, (_list)); \ ++ list_add_tail(&(_new)->list, (_list)); \ + } \ + } while (0) + +-- +2.43.0 + diff --git a/0084-upatch-diff-reorganize-relf-struct.patch b/0084-upatch-diff-reorganize-relf-struct.patch new file mode 100644 index 0000000000000000000000000000000000000000..2ee77d8d851dba9ae195e30e054dcde7804c0f4f --- /dev/null +++ b/0084-upatch-diff-reorganize-relf-struct.patch @@ -0,0 +1,303 @@ +From 86401af6eff9cbc17450877f56a7b21c668dfef4 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 9 May 2025 17:10:03 +0800 +Subject: [PATCH] upatch-diff: reorganize relf struct + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 75 ++++++++++++++++---------------- + upatch-diff/elf-correlate.c | 4 +- + upatch-diff/running-elf.c | 34 +++++++-------- + upatch-diff/running-elf.h | 19 ++++---- + upatch-diff/upatch-elf.h | 2 +- + 5 files changed, 67 insertions(+), 67 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 9973ee0..b9ec36d 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -340,8 +340,8 @@ static bool has_function_prefix(const char *sym_name) + return false; + } + +-static struct symbol* match_uelf_local_symbol(struct upatch_elf *uelf, +- struct symbol *start_sym, struct debug_symbol *relf_sym) ++static struct symbol* find_uelf_local_sym(struct upatch_elf *uelf, ++ struct symbol *start_sym, struct relf_symbol *relf_sym) + { + struct symbol *uelf_sym = start_sym; + list_for_each_entry_continue(uelf_sym, &uelf->symbols, list) { +@@ -364,11 +364,11 @@ static struct symbol* match_uelf_local_symbol(struct upatch_elf *uelf, + return NULL; + } + +-static struct debug_symbol* match_relf_local_symbol(struct running_elf *relf, +- int start_index, struct symbol *uelf_sym) ++static struct relf_symbol* find_relf_local_sym(struct running_elf *relf, ++ struct relf_symbol *relf_file, struct symbol *uelf_sym) + { +- for (int i = start_index + 1; i < relf->obj_nr; i++) { +- struct debug_symbol *relf_sym = &relf->obj_syms[i]; ++ for (int i = relf_file->index + 1; i < relf->symbol_count; i++) { ++ struct relf_symbol *relf_sym = &relf->symbols[i]; + + if (relf_sym->type == STT_FILE) { + break; // find until next file +@@ -389,12 +389,28 @@ static struct debug_symbol* match_relf_local_symbol(struct running_elf *relf, + return NULL; + } + ++static struct relf_symbol* find_relf_file_sym(struct running_elf *relf, ++ struct symbol *file_sym) ++{ ++ for (int i = 0; i < relf->symbol_count; i++) { ++ struct relf_symbol *relf_sym = &relf->symbols[i]; ++ ++ if (relf_sym->type != STT_FILE) { ++ continue; ++ } ++ if (strcmp(file_sym->name, relf_sym->name) == 0) { ++ return relf_sym; ++ } ++ } ++ return NULL; ++} ++ + static void match_file_local_symbols( + struct upatch_elf *uelf, struct running_elf *relf, +- struct symbol *uelf_filesym, int relf_fileidx) ++ struct symbol *uelf_file, struct relf_symbol *relf_file) + { +- for (int i = relf_fileidx + 1; i < relf->obj_nr; i++) { +- struct debug_symbol *sym = &relf->obj_syms[i]; ++ for (int i = relf_file->index + 1; i < relf->symbol_count; i++) { ++ struct relf_symbol *sym = &relf->symbols[i]; + + if (sym->type == STT_FILE) { + break; // match within current file +@@ -407,13 +423,13 @@ static void match_file_local_symbols( + continue; + } + +- struct symbol *matched = match_uelf_local_symbol(uelf, uelf_filesym, sym); ++ struct symbol *matched = find_uelf_local_sym(uelf, uelf_file, sym); + if (matched == NULL) { + ERROR("Cannot find symbol '%s' in %s", sym->name, g_uelf_name); + } + } + +- struct symbol *sym = uelf_filesym; ++ struct symbol *sym = uelf_file; + list_for_each_entry_continue(sym, &uelf->symbols, list) { + if (sym->type == STT_FILE) { + break; // match within current file +@@ -429,34 +445,17 @@ static void match_file_local_symbols( + continue; + } + +- struct debug_symbol *matched = match_relf_local_symbol(relf, relf_fileidx, sym); ++ struct relf_symbol *matched = find_relf_local_sym(relf, relf_file, sym); + if (matched == NULL) { + ERROR("Cannot find symbol '%s' in %s", sym->name, g_relf_name); + } +- if ((sym->debug_sym != NULL) && (sym->debug_sym != matched)) { ++ if ((sym->relf_sym != NULL) && (sym->relf_sym != matched)) { + ERROR("Found duplicated symbol '%s' in %s", sym->name, g_relf_name); + } +- sym->debug_sym = matched; ++ sym->relf_sym = matched; + } + } + +-static bool find_debug_file_symbol(struct running_elf *relf, +- struct symbol *file_sym, int *index) +-{ +- for (int i = 0; i < relf->obj_nr; i++) { +- struct debug_symbol *debug_sym = &relf->obj_syms[i]; +- +- if (debug_sym->type != STT_FILE) { +- continue; +- } +- if (strcmp(file_sym->name, debug_sym->name) == 0) { +- *index = i; +- return true; +- } +- } +- return false; +-} +- + /* + * Because there can be duplicate symbols in elf, we need correlate each symbol + * from source elf to it's corresponding symbol in running elf. +@@ -467,17 +466,17 @@ static bool find_debug_file_symbol(struct running_elf *relf, + */ + static void match_local_symbols(struct upatch_elf *uelf, struct running_elf *relf) + { +- struct symbol *uelf_filesym = NULL; ++ struct symbol *uelf_file = NULL; + +- list_for_each_entry(uelf_filesym, &uelf->symbols, list) { +- if ((uelf_filesym->type != STT_FILE) || (uelf_filesym->status != CHANGED)) { ++ list_for_each_entry(uelf_file, &uelf->symbols, list) { ++ if ((uelf_file->type != STT_FILE) || (uelf_file->status != CHANGED)) { + continue; + } +- int relf_fileidx = 0; +- if (!find_debug_file_symbol(relf, uelf_filesym, &relf_fileidx)) { +- ERROR("Cannot find file '%s' in %s", uelf_filesym->name, g_relf_name); ++ struct relf_symbol *relf_file = find_relf_file_sym(relf, uelf_file); ++ if (relf_file == NULL) { ++ ERROR("Cannot find file '%s' in %s", uelf_file->name, g_relf_name); + } +- match_file_local_symbols(uelf, relf, uelf_filesym, relf_fileidx); ++ match_file_local_symbols(uelf, relf, uelf_file, relf_file); + } + } + +diff --git a/upatch-diff/elf-correlate.c b/upatch-diff/elf-correlate.c +index 9738784..59069a3 100644 +--- a/upatch-diff/elf-correlate.c ++++ b/upatch-diff/elf-correlate.c +@@ -42,8 +42,8 @@ static void correlate_symbol(struct symbol *sym_orig, + sym_patched->name = sym_orig->name; + sym_patched->name_source = DATA_SOURCE_REF; + } +- if (sym_orig->debug_sym && !sym_patched->debug_sym) { +- sym_patched->debug_sym = sym_orig->debug_sym; ++ if (sym_orig->relf_sym && !sym_patched->relf_sym) { ++ sym_patched->relf_sym = sym_orig->relf_sym; + } + } + +diff --git a/upatch-diff/running-elf.c b/upatch-diff/running-elf.c +index f984a26..db44cb4 100644 +--- a/upatch-diff/running-elf.c ++++ b/upatch-diff/running-elf.c +@@ -75,29 +75,29 @@ void relf_open(struct running_elf *relf, const char *name) + if (!data) { + ERROR("Failed to read file '%s' section data, %s", name, elf_errmsg(0)); + } +- +- relf->obj_nr = (int)(shdr.sh_size / shdr.sh_entsize); +- relf->obj_syms = calloc((size_t)relf->obj_nr, sizeof(struct debug_symbol)); +- if (!relf->obj_syms) { ++ relf->symbol_count = (int)(shdr.sh_size / shdr.sh_entsize); ++ relf->symbols = calloc((size_t)relf->symbol_count, sizeof(struct relf_symbol)); ++ if (!relf->symbols) { + ERROR("Failed to alloc memory, %s", strerror(errno)); + } + +- for (int i = 0; i < relf->obj_nr; i++) { ++ for (int i = 0; i < relf->symbol_count; i++) { + if (!gelf_getsym(data, i, &sym)) { + ERROR("Failed to read file '%s' symbol, index=%d, %s", + name, i, elf_errmsg(0)); + } +- relf->obj_syms[i].name = elf_strptr(relf->elf, ++ relf->symbols[i].name = elf_strptr(relf->elf, + shdr.sh_link, sym.st_name); +- if (!relf->obj_syms[i].name) { ++ if (!relf->symbols[i].name) { + ERROR("Failed to read file '%s' symbol name, index=%d, %s", + name, i, elf_errmsg(0)); + } +- relf->obj_syms[i].type = GELF_ST_TYPE(sym.st_info); +- relf->obj_syms[i].bind = GELF_ST_BIND(sym.st_info); +- relf->obj_syms[i].shndx = sym.st_shndx; +- relf->obj_syms[i].addr = sym.st_value; +- relf->obj_syms[i].size = sym.st_size; ++ relf->symbols[i].index = i; ++ relf->symbols[i].type = GELF_ST_TYPE(sym.st_info); ++ relf->symbols[i].bind = GELF_ST_BIND(sym.st_info); ++ relf->symbols[i].shndx = sym.st_shndx; ++ relf->symbols[i].addr = sym.st_value; ++ relf->symbols[i].size = sym.st_size; + } + } + +@@ -106,8 +106,8 @@ void relf_close(struct running_elf *relf) + if (relf == NULL) { + return; + } +- if (relf->obj_syms) { +- free(relf->obj_syms); ++ if (relf->symbols) { ++ free(relf->symbols); + } + if (relf->elf) { + elf_end(relf->elf); +@@ -122,13 +122,13 @@ void relf_close(struct running_elf *relf) + bool lookup_relf(struct running_elf *relf, struct symbol *lookup_sym, + struct lookup_result *result) + { +- struct debug_symbol *symbol = NULL; ++ struct relf_symbol *symbol = NULL; + + log_debug("looking up symbol '%s'\n", lookup_sym->name); + memset(result, 0, sizeof(*result)); + +- for (int i = 0; i < relf->obj_nr; i++) { +- symbol = &relf->obj_syms[i]; ++ for (int i = 0; i < relf->symbol_count; i++) { ++ symbol = &relf->symbols[i]; + + if (result->symbol != NULL && symbol->type == STT_FILE) { + break; +diff --git a/upatch-diff/running-elf.h b/upatch-diff/running-elf.h +index 23dd9c1..ae05d83 100644 +--- a/upatch-diff/running-elf.h ++++ b/upatch-diff/running-elf.h +@@ -34,13 +34,8 @@ + + struct symbol; + +-struct lookup_result { +- struct debug_symbol *symbol; +- unsigned long sympos; +- bool global; +-}; +- +-struct debug_symbol { ++struct relf_symbol { ++ int index; + char *name; + unsigned char type, bind; + unsigned int shndx; +@@ -49,13 +44,19 @@ struct debug_symbol { + }; + + struct running_elf { +- int obj_nr; +- struct debug_symbol *obj_syms; + int fd; + Elf *elf; ++ struct relf_symbol *symbols; ++ int symbol_count; + bool is_exec; + }; + ++struct lookup_result { ++ struct relf_symbol *symbol; ++ unsigned long sympos; ++ bool global; ++}; ++ + void relf_open(struct running_elf *relf, const char *name); + void relf_close(struct running_elf *relf); + +diff --git a/upatch-diff/upatch-elf.h b/upatch-diff/upatch-elf.h +index d8af728..eeb7fb2 100644 +--- a/upatch-diff/upatch-elf.h ++++ b/upatch-diff/upatch-elf.h +@@ -112,7 +112,7 @@ struct symbol { + GElf_Sym sym; + char *name; + enum data_source name_source; +- struct debug_symbol *debug_sym; ++ struct relf_symbol *relf_sym; + unsigned int index; + unsigned char bind; + unsigned char type; +-- +2.43.0 + diff --git a/0085-upatch-diff-fix-cannot-find-local-symbol-in-relf-iss.patch b/0085-upatch-diff-fix-cannot-find-local-symbol-in-relf-iss.patch new file mode 100644 index 0000000000000000000000000000000000000000..57c7049f7f43142afaa6861ceaf452dff20d318a --- /dev/null +++ b/0085-upatch-diff-fix-cannot-find-local-symbol-in-relf-iss.patch @@ -0,0 +1,56 @@ +From ac18ffa5525029a4b69b11540e8f818a95d0a739 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 9 May 2025 18:04:16 +0800 +Subject: [PATCH] upatch-diff: fix cannot find local symbol in relf issue + + In some case, compiler may generate multiple parts of +function symbol like 'xxx.part.0' or 'xxxx.cold', which +is called subfunction. They were already handled by +detect_child_functions(). + + When matching local symbols between objects & debuginfos, +the debuginfo may only contain function symbol, but no +subfuction symbol, even they were compiled with same compiler. + + To solve this, we need to check if the symbol is a subfunction +and stop searching it in debuginfo file. + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 3 +++ + upatch-diff/elf-common.h | 5 +++++ + 2 files changed, 8 insertions(+) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index b9ec36d..291542f 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -438,6 +438,9 @@ static void match_file_local_symbols( + ((sym->type != STT_FUNC) && (sym->type != STT_OBJECT))) { + continue; + } ++ if (is_subfunction_sym(sym)) { ++ continue; ++ } + if (has_function_prefix(sym->name)) { + continue; + } +diff --git a/upatch-diff/elf-common.h b/upatch-diff/elf-common.h +index 01a1152..d3dbd2f 100644 +--- a/upatch-diff/elf-common.h ++++ b/upatch-diff/elf-common.h +@@ -288,6 +288,11 @@ static inline bool is_local_func_sym(struct symbol *sym) + return sym->bind == STB_LOCAL && sym->type == STT_FUNC; + } + ++static inline bool is_subfunction_sym(struct symbol *sym) ++{ ++ return sym->parent != NULL; ++} ++ + static inline bool is_local_sym(struct symbol *sym) + { + return sym->bind == STB_LOCAL; +-- +2.43.0 + diff --git a/0086-upatch-diff-fix-coredump-in-checking-symbol.patch b/0086-upatch-diff-fix-coredump-in-checking-symbol.patch new file mode 100644 index 0000000000000000000000000000000000000000..6f6f8a6475b6753b1810627d13f121d25b12e32c --- /dev/null +++ b/0086-upatch-diff-fix-coredump-in-checking-symbol.patch @@ -0,0 +1,27 @@ +From 7040621e4d664fab6ef9e765e575c104f5c28c93 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 9 May 2025 18:32:51 +0800 +Subject: [PATCH] upatch-diff: fix coredump in checking symbol + +Signed-off-by: renoseven +--- + upatch-diff/elf-common.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/upatch-diff/elf-common.c b/upatch-diff/elf-common.c +index 0ac8188..3636c01 100644 +--- a/upatch-diff/elf-common.c ++++ b/upatch-diff/elf-common.c +@@ -34,6 +34,9 @@ static bool is_dynamic_debug_symbol(struct symbol *sym) + NULL, + }; + ++ if (sym->sec == NULL) { ++ return false; ++ } + if ((sym->type == STT_OBJECT) || (sym->type == STT_SECTION)) { + const char **sec_name; + for (sec_name = SEC_NAMES; *sec_name; sec_name++) { +-- +2.43.0 + diff --git a/0087-upatch-diff-fix-compare-common-section-symbol-failur.patch b/0087-upatch-diff-fix-compare-common-section-symbol-failur.patch new file mode 100644 index 0000000000000000000000000000000000000000..7e38147a542af64aef6a163723eb61320d989866 --- /dev/null +++ b/0087-upatch-diff-fix-compare-common-section-symbol-failur.patch @@ -0,0 +1,32 @@ +From 18abe2a81f2e1af6a98e9fc8290e670e6b46812b Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 12 May 2025 09:53:10 +0800 +Subject: [PATCH] upatch-diff: fix compare common section symbol failure + + Comparing symbol with st_shndx == SHN_COMMON would cause an +error "Symbol '%s' don't have section", which is not as expected. +We need to handle SHN_COMMON before comparasion. + +Signed-off-by: renoseven +--- + upatch-diff/elf-compare.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c +index 9aa92bf..227b600 100644 +--- a/upatch-diff/elf-compare.c ++++ b/upatch-diff/elf-compare.c +@@ -44,7 +44,9 @@ static void compare_correlated_symbol(struct symbol *sym, struct symbol *twin) + /* + * For local symbols, we handle them based on their matching sections. + */ +- if ((sym->sym.st_shndx == SHN_UNDEF) || (sym->sym.st_shndx == SHN_ABS)) { ++ if ((sym->sym.st_shndx == SHN_UNDEF) || ++ (sym->sym.st_shndx == SHN_ABS) || ++ (sym->sym.st_shndx == SHN_COMMON)) { + sym->status = SAME; + return; + } +-- +2.43.0 + diff --git a/0088-upatch-diff-optimize-debug-output.patch b/0088-upatch-diff-optimize-debug-output.patch new file mode 100644 index 0000000000000000000000000000000000000000..599a26f77e86c104f23d68de26235bc8bb6752ae --- /dev/null +++ b/0088-upatch-diff-optimize-debug-output.patch @@ -0,0 +1,591 @@ +From 8dcce329e2f8e2297fe96520d12f0f7de4f7e08e Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 12 May 2025 11:50:09 +0800 +Subject: [PATCH] upatch-diff: optimize debug output + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 30 ++------ + upatch-diff/elf-compare.c | 12 +--- + upatch-diff/elf-correlate.c | 9 --- + upatch-diff/elf-create.c | 38 ---------- + upatch-diff/elf-create.h | 2 - + upatch-diff/elf-debug.c | 120 +++++++++++++------------------ + upatch-diff/elf-debug.h | 5 +- + upatch-diff/upatch-elf.c | 39 ---------- + 8 files changed, 60 insertions(+), 195 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 291542f..c7be45d 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -522,8 +522,8 @@ static void mark_grouped_sections(struct upatch_elf *uelf) + ERROR("Group section not found"); + } + sec->grouped = true; +- log_debug("Marking section '%s' (%d) as grouped\n", +- sec->name, sec->index); ++ log_debug("Marking section grouped, index: %d, name: '%s'\n", ++ sec->index, sec->name); + data++; + } + } +@@ -555,17 +555,12 @@ static void replace_section_syms(struct upatch_elf *uelf) + rela->sym->type != STT_SECTION) { + continue; + } +- log_debug("Found replace symbol for section '%s'\n", +- rela->sym->name); +- + /* + * for section symbol, rela->sym->sec is the section itself. + * rela->sym->sec->sym is the bundleable symbol which is + * a function or object. + */ + if (rela->sym->sec->sym) { +- log_debug("Act: Replace it with '%s' <- '%s'\n", +- rela->sym->sec->sym->name, rela->sym->sec->name); + rela->sym = rela->sym->sec->sym; + if (rela->sym->sym.st_value != 0) { + ERROR("Symbol offset is not zero."); +@@ -601,14 +596,10 @@ static void replace_section_syms(struct upatch_elf *uelf) + if (is_mapping_symbol(uelf, sym)) { + continue; + } +- log_debug("Find relocation reference for empty symbol.\n"); + } else if (target_off < start || target_off >= end) { + continue; + } + +- log_debug("'%s': Replacing '%s+%ld' reference with '%s+%ld'\n", +- relasec->name, rela->sym->name, rela->addend, +- sym->name, rela->addend - start); + found = true; + rela->sym = sym; + rela->addend -= start; +@@ -680,8 +671,8 @@ static void mark_ignored_sections(struct upatch_elf *uelf) + sec->base->name : sec->name; + if (strncmp(sec_name, ignored_name, name_len) == 0) { + sec->ignored = true; +- log_debug("Marking section '%s' (%d) as ignored\n", +- sec->name, sec->index); ++ log_debug("Marking section ignored, index: %d, name: '%s'\n", ++ sec->index, sec->name); + break; + } + } +@@ -734,8 +725,6 @@ static void include_symbol(struct symbol *sym) + * might be needed: either permanently for a rela, or temporarily for + * the later creation of a dynrela. + */ +- log_debug("Include symbol '%s', status: %s\n", +- sym->name, status_str(sym->status)); + sym->include = true; + /* + * For special static symbols, we need include it's section +@@ -763,8 +752,6 @@ static void include_section(struct section *sec) + return; + } + +- log_debug("Include section '%s', status: %s\n", +- sec->name, status_str(sec->status)); + sec->include = true; + + if (is_rela_section(sec)) { +@@ -1021,13 +1008,13 @@ int main(int argc, char **argv) + + upatch_correlate_elf(&uelf_source, &uelf_patched); + upatch_correlate_static_local_variables(&uelf_source, &uelf_patched); ++ upatch_print_correlation(&uelf_patched); + + upatch_compare_correlated_elements(&uelf_patched); + mark_file_symbols(&uelf_source); + match_local_symbols(&uelf_source, &relf); + + include_standard_elements(&uelf_patched); +- + int change_count = include_changes(&uelf_patched); + if (change_count == 0) { + log_normal("No functional changes\n"); +@@ -1036,11 +1023,8 @@ int main(int argc, char **argv) + relf_close(&relf); + return 0; + } +- + upatch_print_changes(&uelf_patched); + +- upatch_dump_kelf(&uelf_patched); +- + verify_patchability(&uelf_patched); + + include_special_local_section(&uelf_patched); +@@ -1069,8 +1053,6 @@ int main(int argc, char **argv) + + upatch_rebuild_relocations(&uelf_out); + +- upatch_check_relocations(); +- + upatch_create_shstrtab(&uelf_out); + + upatch_create_strtab(&uelf_out); +@@ -1079,8 +1061,6 @@ int main(int argc, char **argv) + + upatch_create_symtab(&uelf_out); + +- upatch_dump_kelf(&uelf_out); +- + upatch_write_output_elf(&uelf_out, uelf_patched.elf, args.output_obj, 0664); + log_normal("Done\n"); + +diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c +index 227b600..97daa0b 100644 +--- a/upatch-diff/elf-compare.c ++++ b/upatch-diff/elf-compare.c +@@ -86,7 +86,6 @@ void upatch_compare_symbols(struct upatch_elf *uelf) + } else { + compare_correlated_symbol(sym, sym->twin); + } +- log_debug("Symbol '%s' is %s\n", sym->name, status_str(sym->status)); + } + } + +@@ -163,20 +162,20 @@ static int compare_correlated_section(struct section *sec, struct section *twin) + + if (is_note_section(sec)) { + sec->status = SAME; +- goto out; ++ return 0; + } + /* As above but for aarch64 */ + if (!strcmp(sec->name, ".rela__patchable_function_entries") || + !strcmp(sec->name, "__patchable_function_entries")) { + sec->status = SAME; +- goto out; ++ return 0; + } + /* compare file size and data size(memory size) */ + if (sec->sh.sh_size != twin->sh.sh_size || + sec->data->d_size != twin->data->d_size || + (sec->rela && !twin->rela) || (!sec->rela && twin->rela)) { + sec->status = CHANGED; +- goto out; ++ return 0; + } + + if (is_rela_section(sec)) { +@@ -185,11 +184,6 @@ static int compare_correlated_section(struct section *sec, struct section *twin) + compare_correlated_nonrela_section(sec, twin); + } + +-out: +- if (sec->status == CHANGED) { +- log_debug("section %s has changed\n", sec->name); +- } +- + return 0; + } + +diff --git a/upatch-diff/elf-correlate.c b/upatch-diff/elf-correlate.c +index 59069a3..d5e76f6 100644 +--- a/upatch-diff/elf-correlate.c ++++ b/upatch-diff/elf-correlate.c +@@ -30,9 +30,6 @@ + static void correlate_symbol(struct symbol *sym_orig, + struct symbol *sym_patched) + { +- log_debug("correlate symbol %s <-> %s\n", +- sym_orig->name, sym_patched->name); +- + sym_orig->twin = sym_patched; + sym_patched->twin = sym_orig; + sym_orig->status = sym_patched->status = SAME; +@@ -109,9 +106,6 @@ void upatch_correlate_symbols(struct upatch_elf *uelf_source, + static void correlate_section_impl(struct section *sec_orig, + struct section *sec_patched) + { +- log_debug("correlate section %s <-> %s\n", +- sec_orig->name, sec_patched->name); +- + sec_orig->twin = sec_patched; + sec_patched->twin = sec_orig; + /* set initial status, might change */ +@@ -384,15 +378,12 @@ void upatch_correlate_static_local_variables(struct upatch_elf *uelf_source, + continue; + } + +- log_debug("find normal symbol %s\n", sym->name); + if (sym->twin) { + uncorrelate_symbol(sym); + } + + bundled = (sym == sym->sec->sym) ? 1 : 0; + if (bundled && sym->sec->twin) { +- log_debug("find bundled static symbol %s\n", sym->name); +- + uncorrelate_section(sym->sec); + if (sym->sec->secsym) { + uncorrelate_symbol(sym->sec->secsym); +diff --git a/upatch-diff/elf-create.c b/upatch-diff/elf-create.c +index 63dbdb2..964079d 100644 +--- a/upatch-diff/elf-create.c ++++ b/upatch-diff/elf-create.c +@@ -384,25 +384,6 @@ void upatch_rebuild_relocations(struct upatch_elf *uelf) + } + } + +-void upatch_check_relocations(void) +-{ +- log_debug("upatch_check_relocations does not work now.\n"); +- return; +-} +- +-static void print_strtab(char *buf, size_t size) +-{ +- size_t i; +- +- for (i = 0; i < size; i++) { +- if (buf[i] == 0) { +- log_debug("\\0"); +- } else { +- log_debug("%c", buf[i]); +- } +- } +-} +- + void upatch_create_shstrtab(struct upatch_elf *uelf) + { + struct section *shstrtab; +@@ -451,17 +432,6 @@ void upatch_create_shstrtab(struct upatch_elf *uelf) + shstrtab->data->d_buf = buf; + shstrtab->data->d_size = size; + shstrtab->dbuf_source = DATA_SOURCE_ALLOC; +- +- log_debug("shstrtab: "); +- print_strtab(buf, size); +- log_debug("\n"); +- +- list_for_each_entry(sec, &uelf->sections, list) { +- if (sec->ignored) { +- continue; +- } +- log_debug("%s @ shstrtab offset %d\n", sec->name, sec->sh.sh_name); +- } + } + + void upatch_create_strtab(struct upatch_elf *uelf) +@@ -507,14 +477,6 @@ void upatch_create_strtab(struct upatch_elf *uelf) + strtab->data->d_buf = buf; + strtab->data->d_size = size; + strtab->dbuf_source = DATA_SOURCE_ALLOC; +- +- log_debug("strtab: "); +- print_strtab(buf, size); +- log_debug("\n"); +- +- list_for_each_entry(sym, &uelf->symbols, list) { +- log_debug("%s @ strtab offset %d\n", sym->name, sym->sym.st_name); +- } + } + + void upatch_create_symtab(struct upatch_elf *uelf) +diff --git a/upatch-diff/elf-create.h b/upatch-diff/elf-create.h +index f18d40b..18778b5 100644 +--- a/upatch-diff/elf-create.h ++++ b/upatch-diff/elf-create.h +@@ -43,8 +43,6 @@ void upatch_reindex_elements(struct upatch_elf *); + + void upatch_rebuild_relocations(struct upatch_elf *); + +-void upatch_check_relocations(void); +- + void upatch_create_shstrtab(struct upatch_elf *); + + void upatch_create_strtab(struct upatch_elf *); +diff --git a/upatch-diff/elf-debug.c b/upatch-diff/elf-debug.c +index 90e112b..44b0e09 100644 +--- a/upatch-diff/elf-debug.c ++++ b/upatch-diff/elf-debug.c +@@ -31,17 +31,58 @@ + #include "elf-debug.h" + #include "upatch-elf.h" + ++void upatch_print_correlation(struct upatch_elf *uelf) ++{ ++ if (uelf == NULL) { ++ return; ++ } ++ ++ log_debug("\n------------------------------\n"); ++ log_debug("Section\n"); ++ log_debug("------------------------------\n"); ++ struct section *sec; ++ list_for_each_entry(sec, &uelf->sections, list) { ++ if (sec->twin != NULL) { ++ log_debug("index: %04d, name: '%s' -> index: %04d, name: '%s'\n", ++ sec->index, sec->name, sec->twin->index, sec->twin->name); ++ } else { ++ log_debug("index: %04d, name: '%s' -> None\n", ++ sec->index, sec->name); ++ } ++ } ++ log_debug("------------------------------\n"); ++ log_debug("\n"); ++ log_debug("------------------------------\n"); ++ log_debug("Symbol\n"); ++ log_debug("------------------------------\n"); ++ struct symbol *sym; ++ list_for_each_entry(sym, &uelf->symbols, list) { ++ if (sym->twin != NULL) { ++ log_debug("index: %04d, name: '%s' -> index: %04d, name: '%s'\n", ++ sym->index, sym->name, sym->twin->index, sym->twin->name); ++ } else { ++ log_debug("index: %04d, name: '%s' -> None\n", ++ sym->index, sym->name); ++ } ++ } ++ log_debug("------------------------------\n"); ++} ++ + void upatch_print_changes(struct upatch_elf *uelf) + { +- struct symbol *sym = NULL; +- struct section *sec = NULL; ++ struct symbol *sym; ++ struct section *sec; + +- log_normal("------------------------------\n"); ++ if (uelf == NULL) { ++ return; ++ } ++ ++ log_normal("\n------------------------------\n"); + log_normal("New symbol\n"); + log_normal("------------------------------\n"); + list_for_each_entry(sym, &uelf->symbols, list) { + if (sym->status == NEW) { +- log_normal("idx: %04u, name: '%s'\n", sym->index, sym->name); ++ log_normal("index: %04d, name: '%s'\n", sym->index, sym->name); + } + } + log_normal("------------------------------\n"); +@@ -51,7 +92,7 @@ void upatch_print_changes(struct upatch_elf *uelf) + log_normal("------------------------------\n"); + list_for_each_entry(sec, &uelf->sections, list) { + if (sec->status == NEW) { +- log_normal("idx: %04u, name: '%s'\n", sec->index, sec->name); ++ log_normal("index: %04d, name: '%s'\n", sec->index, sec->name); + } + } + log_normal("------------------------------\n"); +@@ -61,7 +102,7 @@ void upatch_print_changes(struct upatch_elf *uelf) + log_normal("------------------------------\n"); + list_for_each_entry(sym, &uelf->symbols, list) { + if (sym->status == CHANGED) { +- log_normal("idx: %04u, name: '%s'\n", sym->index, sym->name); ++ log_normal("index: %04d, name: '%s'\n", sym->index, sym->name); + } + } + log_normal("------------------------------\n"); +@@ -71,7 +112,7 @@ void upatch_print_changes(struct upatch_elf *uelf) + log_normal("------------------------------\n"); + list_for_each_entry(sec, &uelf->sections, list) { + if (sec->status == CHANGED) { +- log_normal("idx: %04u, name: '%s'\n", sec->index, sec->name); ++ log_normal("index: %04d, name: '%s'\n", sec->index, sec->name); + } + } + log_normal("------------------------------\n"); +@@ -81,7 +122,7 @@ void upatch_print_changes(struct upatch_elf *uelf) + log_normal("------------------------------\n"); + list_for_each_entry(sym, &uelf->symbols, list) { + if (sym->include) { +- log_normal("idx: %04u, name: '%s', status: %s\n", ++ log_normal("index: %04d, name: '%s', status: %s\n", + sym->index, sym->name, status_str(sym->status)); + } + } +@@ -92,70 +133,9 @@ void upatch_print_changes(struct upatch_elf *uelf) + log_normal("------------------------------\n"); + list_for_each_entry(sec, &uelf->sections, list) { + if (sec->include) { +- log_normal("idx: %04u, name: '%s', status: %s\n", ++ log_normal("index: %04d, name: '%s', status: %s\n", + sec->index, sec->name, status_str(sec->status)); + } + } + log_normal("------------------------------\n"); + } +- +-void upatch_dump_kelf(struct upatch_elf *uelf) +-{ +- struct section *sec; +- struct symbol *sym; +- struct rela *rela; +- +- log_debug("\n=== Sections ===\n"); +- list_for_each_entry(sec, &uelf->sections, list) { +- log_debug("%02d %s (%s)", +- sec->index, sec->name, status_str(sec->status)); +- if (is_rela_section(sec)) { +- if (sec->ignored) { +- continue; +- } +- log_debug(", base-> %s\n", sec->base->name); +- log_debug("rela section expansion\n"); +- list_for_each_entry(rela, &sec->relas, list) { +- log_debug("sym %d, offset %ld, type %d, %s %s %ld\n", +- rela->sym->index, rela->offset, +- rela->type, rela->sym->name, +- (rela->addend < 0) ? "-" : "+", +- labs(rela->addend)); +- } +- } else { +- if (sec->sym) { +- log_debug(", sym-> %s", sec->sym->name); +- } +- if (sec->secsym) { +- log_debug(", secsym-> %s", sec->secsym->name); +- } +- if (sec->rela) { +- log_debug(", rela-> %s", sec->rela->name); +- } +- } +- log_debug("\n"); +- } +- +- log_debug("\n=== Symbols ===\n"); +- list_for_each_entry(sym, &uelf->symbols, list) { +- log_debug("sym %02d, type %d, bind %d, ndx %02d, name %s (%s)", +- sym->index, sym->type, sym->bind, sym->sym.st_shndx, +- sym->name, status_str(sym->status)); +- if (sym->sec && (sym->type == STT_FUNC || sym->type == STT_OBJECT)) { +- log_debug(" -> %s", sym->sec->name); +- } +- log_debug("\n"); +- } +-} +- +-/* debuginfo releated */ +-static inline bool skip_bytes(unsigned char **iter, unsigned char *end, +- unsigned int len) +-{ +- if ((unsigned int)(end - *iter) < len) { +- *iter = end; +- return false; +- } +- *iter += len; +- return true; +-} +diff --git a/upatch-diff/elf-debug.h b/upatch-diff/elf-debug.h +index 7c8db40..09122f6 100644 +--- a/upatch-diff/elf-debug.h ++++ b/upatch-diff/elf-debug.h +@@ -27,8 +27,7 @@ + + #include "upatch-elf.h" + +-void upatch_print_changes(struct upatch_elf *); +- +-void upatch_dump_kelf(struct upatch_elf *); ++void upatch_print_correlation(struct upatch_elf *uelf); ++void upatch_print_changes(struct upatch_elf *uelf); + + #endif /* __UPATCH_ELF_DEBUG_H_ */ +diff --git a/upatch-diff/upatch-elf.c b/upatch-diff/upatch-elf.c +index 2f88a92..81567f5 100644 +--- a/upatch-diff/upatch-elf.c ++++ b/upatch-diff/upatch-elf.c +@@ -56,7 +56,6 @@ static void create_section_list(struct upatch_elf *uelf) + ERROR("elf_getshdrstrndx with error %s", elf_errmsg(0)); + } + +- log_debug("=== section list (%zu) ===\n", sections_nr); + while (sections_nr--) { + ALLOC_LINK(sec, &uelf->sections); + +@@ -87,9 +86,6 @@ static void create_section_list(struct upatch_elf *uelf) + if (sec->sh.sh_type == SHT_SYMTAB_SHNDX) { + uelf->symtab_shndx = sec->data; /* correct ? */ + } +- +- log_debug("ndx %02d, data %p, size %zu, name %s\n", +- sec->index, sec->data->d_buf, sec->data->d_size, sec->name); + } + + if (elf_nextscn(uelf->elf, scn)) { +@@ -114,7 +110,6 @@ static void create_symbol_list(struct upatch_elf *uelf) + + symbols_nr = (unsigned int)(symtab->sh.sh_size / symtab->sh.sh_entsize); + +- log_debug("\n=== symbol list (%d entries) ===\n", symbols_nr); + while (symbols_nr--) { + ALLOC_LINK(sym, &uelf->symbols); + INIT_LIST_HEAD(&sym->children); +@@ -157,12 +152,6 @@ static void create_symbol_list(struct upatch_elf *uelf) + sym->name = sym->sec->name; + } + } +- log_debug("sym %02d, type %d, bind %d, ndx %02d, name %s", +- sym->index, sym->type, sym->bind, sym->sym.st_shndx, sym->name); +- if (sym->sec) { +- log_debug(" -> %s", sym->sec->name); +- } +- log_debug("\n"); + } + } + +@@ -173,7 +162,6 @@ static void create_rela_list(struct upatch_elf *uelf, struct section *relasec) + + unsigned int symndx; + int index = 0; +- int skip = 0; + + INIT_LIST_HEAD(&relasec->relas); + +@@ -182,23 +170,9 @@ static void create_rela_list(struct upatch_elf *uelf, struct section *relasec) + if (!relasec->base) { + ERROR("no base section found for relocation section %s", relasec->name); + } +- + relasec->base->rela = relasec; + rela_nr = relasec->sh.sh_size / relasec->sh.sh_entsize; + +- log_debug("\n=== rela list for %s (%ld entries) ===\n", +- relasec->base->name, rela_nr); +- +- if (is_debug_section(relasec)) { +- log_debug("skipping rela listing for .debug_* section\n"); +- skip = 1; +- } +- +- if (is_note_section(relasec)) { +- log_debug("skipping rela listing for .note_* section\n"); +- skip = 1; +- } +- + while (rela_nr--) { + ALLOC_LINK(rela, &relasec->relas); + +@@ -226,19 +200,6 @@ static void create_rela_list(struct upatch_elf *uelf, struct section *relasec) + rela->sym->name, rela->addend); + } + } +- +- if (skip) { +- continue; +- } +- +- log_debug("offset %ld, type %d, %s %s %ld", rela->offset, +- rela->type, rela->sym->name, +- (rela->addend < 0) ? "-" : "+", labs(rela->addend)); +- if (rela->string) { +- // rela->string is not utf8 +- log_debug(" string = %s", rela->string); +- } +- log_debug("\n"); + } + } + +-- +2.43.0 + diff --git a/0089-upatch-diff-support-text-section-offset.patch b/0089-upatch-diff-support-text-section-offset.patch new file mode 100644 index 0000000000000000000000000000000000000000..157dc131bd8c4d9ed4bce44632a16346f4b07aee --- /dev/null +++ b/0089-upatch-diff-support-text-section-offset.patch @@ -0,0 +1,154 @@ +From f7acf7f2daf4c0bf8f4f5755532f3c9489c87ec0 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 12 May 2025 10:59:38 +0800 +Subject: [PATCH] upatch-diff: support text section offset + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 46 +++++++++++++++++++++++++------- + upatch-diff/elf-create.c | 8 ++++-- + upatch-diff/elf-create.h | 3 ++- + 3 files changed, 45 insertions(+), 12 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index c7be45d..1ffc9f5 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -71,28 +71,42 @@ struct arguments { + char *patched_obj; + char *running_elf; + char *output_obj; ++ unsigned long text_offset; + bool debug; + }; + + static const struct argp_option ARGP_OPTION[] = { +- {"source", 's', "", 0, "Source object", 0}, +- {"patched", 'p', "", 0, "Patched object", 1}, +- {"running", 'r', "", 0, "Running binary file", 2}, +- {"output", 'o', "", 0, "Output object", 3}, +- {"debug", 'd', NULL, 0, "Show debug output", 4}, ++ {"source", 's', "", 0, "Source object", 0}, ++ {"patched", 'p', "", 0, "Patched object", 1}, ++ {"running", 'r', "", 0, "Running binary file", 2}, ++ {"output", 'o', "", 0, "Output object", 3}, ++ {"text-offset", 't', "", 0, "Text section offset", 4}, ++ {"debug", 'd', NULL, 0, "Show debug output", 5}, + {NULL} + }; + static const char ARGP_DOC[] = "Generate a patch object based on source object"; + const char *argp_program_version = PROG_VERSION; + ++static void parse_text_offset(struct argp_state *state, const char *arg) ++{ ++ errno = 0; ++ char *endptr = NULL; ++ ++ unsigned long offset = strtoul(arg, &endptr, 0); ++ if ((errno != 0) || (*endptr != '\0') || ++ ((errno == ERANGE) && (offset == ULONG_MAX))) { ++ argp_error(state, "ERROR: Invalid text section offset '%s'", arg); ++ } ++ ++ struct arguments *arguments = state->input; ++ arguments->text_offset = offset; ++} ++ + static error_t parse_opt(int key, char *arg, struct argp_state *state) + { + struct arguments *arguments = state->input; + + switch (key) { +- case 'd': +- arguments->debug = true; +- break; + case 's': + arguments->source_obj = arg; + break; +@@ -105,6 +119,12 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) + case 'o': + arguments->output_obj = arg; + break; ++ case 't': ++ parse_text_offset(state, arg); ++ break; ++ case 'd': ++ arguments->debug = true; ++ break; + default: + return ARGP_ERR_UNKNOWN; + } +@@ -129,6 +149,13 @@ static bool check_args(struct arguments *arguments) + log_error("The argument '--output ' requires a value\n"); + return false; + } ++ if (arguments->text_offset > UINT32_MAX) { ++ ERROR("Text section offset 0x%lx overflow", arguments->text_offset); ++ } ++ if ((arguments->text_offset & 0xFFF) != 0) { ++ ERROR("Text section offset 0x%lx is not 4K-aligned", ++ arguments->text_offset); ++ } + return true; + } + +@@ -141,6 +168,7 @@ static void show_program_info(struct arguments *arguments) + log_debug("patched object: %s\n", arguments->patched_obj); + log_debug("running binary: %s\n", arguments->running_elf); + log_debug("output object: %s\n", arguments->output_obj); ++ log_debug("text offset: 0x%lx\n", arguments->text_offset); + log_debug("------------------------------\n\n"); + } + +@@ -1033,7 +1061,7 @@ int main(int argc, char **argv) + + upatch_create_strings_elements(&uelf_out); + +- upatch_create_patches_sections(&uelf_out, &relf); ++ upatch_create_patches_sections(&uelf_out, &relf, args.text_offset); + + create_kpatch_arch_section(); + +diff --git a/upatch-diff/elf-create.c b/upatch-diff/elf-create.c +index 964079d..eea1315 100644 +--- a/upatch-diff/elf-create.c ++++ b/upatch-diff/elf-create.c +@@ -138,7 +138,7 @@ void upatch_create_strings_elements(struct upatch_elf *uelf) + + /* create upatch func info section */ + void upatch_create_patches_sections(struct upatch_elf *uelf, +- struct running_elf *relf) ++ struct running_elf *relf, unsigned long text_offset) + { + struct symbol *sym; + struct symbol *strsym; +@@ -190,7 +190,11 @@ void upatch_create_patches_sections(struct upatch_elf *uelf, + sym->name, symbol.symbol->name, symbol.sympos, symbol.symbol->size); + + /* ATTENTION: kpatch convert global symbols to local symbols here. */ +- funcs[index].old_addr = symbol.symbol->addr; ++ if (symbol.symbol->addr < text_offset) { ++ ERROR("Text section offset 0x%lx overflow, sym_addr=0x%lx", ++ text_offset, symbol.symbol->addr); ++ } ++ funcs[index].old_addr = symbol.symbol->addr - text_offset; + funcs[index].old_size = symbol.symbol->size; + funcs[index].new_size = sym->sym.st_size; + funcs[index].sympos = symbol.sympos; +diff --git a/upatch-diff/elf-create.h b/upatch-diff/elf-create.h +index 18778b5..0c76a46 100644 +--- a/upatch-diff/elf-create.h ++++ b/upatch-diff/elf-create.h +@@ -29,7 +29,8 @@ + + void upatch_create_strings_elements(struct upatch_elf *); + +-void upatch_create_patches_sections(struct upatch_elf *, struct running_elf *); ++void upatch_create_patches_sections(struct upatch_elf *, struct running_elf *, ++ unsigned long); + + static inline void create_kpatch_arch_section(void) {} + +-- +2.43.0 + diff --git a/0090-upatch-diff-remove-match_local_symbols.patch b/0090-upatch-diff-remove-match_local_symbols.patch new file mode 100644 index 0000000000000000000000000000000000000000..0d87e4bb20e8934934680875ff6672662975856a --- /dev/null +++ b/0090-upatch-diff-remove-match_local_symbols.patch @@ -0,0 +1,212 @@ +From cc64287f73348ff40de10d4d547c53e0c73fc57a Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 12 May 2025 19:54:45 +0800 +Subject: [PATCH] upatch-diff: remove match_local_symbols() + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 181 ------------------------------- + 1 file changed, 181 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 1ffc9f5..b27351f 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -331,186 +331,6 @@ static void detect_child_functions(struct upatch_elf *uelf) + } + } + +-static bool is_discarded_sym(struct running_elf *relf, struct symbol *sym) +-{ +- if (!sym || !sym->sec || !sym->sec->name) { +- return false; +- } +- /* +- * ".gnu.warning." section is to prevent some symbols +- * in the dynamic library being used by external programs. +- * In the exec program, these sections are discarded in linker. +- * so we discard these symbols. +- */ +- if (relf->is_exec && +- !strncmp(sym->sec->name, ".gnu.warning.", strlen(".gnu.warning."))) { +- return true; +- } +- +- return false; +-} +- +-static bool has_function_prefix(const char *sym_name) +-{ +- static const char *SYM_NAMES[] = { +- "__func__.", +- "__FUNC__.", +- "__PRETTY_FUNCTION__.", +- NULL, +- }; +- +- const char **name; +- for (name = SYM_NAMES; *name; name++) { +- if (strcmp(sym_name, *name) == 0) { +- return true; +- } +- } +- return false; +-} +- +-static struct symbol* find_uelf_local_sym(struct upatch_elf *uelf, +- struct symbol *start_sym, struct relf_symbol *relf_sym) +-{ +- struct symbol *uelf_sym = start_sym; +- list_for_each_entry_continue(uelf_sym, &uelf->symbols, list) { +- if (uelf_sym->type == STT_FILE) { +- break; // find until next file +- } +- if (uelf_sym->bind != STB_LOCAL) { +- continue; +- } +- if ((uelf_sym->type != STT_FUNC) && (uelf_sym->type != STT_OBJECT)) { +- continue; +- } +- if ((uelf_sym->type != relf_sym->type) || +- (strcmp(uelf_sym->name, relf_sym->name) != 0)) { +- continue; +- } +- return uelf_sym; +- } +- +- return NULL; +-} +- +-static struct relf_symbol* find_relf_local_sym(struct running_elf *relf, +- struct relf_symbol *relf_file, struct symbol *uelf_sym) +-{ +- for (int i = relf_file->index + 1; i < relf->symbol_count; i++) { +- struct relf_symbol *relf_sym = &relf->symbols[i]; +- +- if (relf_sym->type == STT_FILE) { +- break; // find until next file +- } +- if (relf_sym->bind != STB_LOCAL) { +- continue; +- } +- if ((relf_sym->type != STT_FUNC) && (relf_sym->type != STT_OBJECT)) { +- continue; +- } +- if ((relf_sym->type != uelf_sym->type) || +- (strcmp(relf_sym->name, uelf_sym->name) != 0)) { +- continue; +- } +- return relf_sym; +- } +- +- return NULL; +-} +- +-static struct relf_symbol* find_relf_file_sym(struct running_elf *relf, +- struct symbol *file_sym) +-{ +- for (int i = 0; i < relf->symbol_count; i++) { +- struct relf_symbol *relf_sym = &relf->symbols[i]; +- +- if (relf_sym->type != STT_FILE) { +- continue; +- } +- if (strcmp(file_sym->name, relf_sym->name) == 0) { +- return relf_sym; +- } +- } +- return NULL; +-} +- +-static void match_file_local_symbols( +- struct upatch_elf *uelf, struct running_elf *relf, +- struct symbol *uelf_file, struct relf_symbol *relf_file) +-{ +- for (int i = relf_file->index + 1; i < relf->symbol_count; i++) { +- struct relf_symbol *sym = &relf->symbols[i]; +- +- if (sym->type == STT_FILE) { +- break; // match within current file +- } +- if ((sym->bind != STB_LOCAL) || +- ((sym->type != STT_FUNC) && (sym->type != STT_OBJECT))) { +- continue; +- } +- if (has_function_prefix(sym->name)) { +- continue; +- } +- +- struct symbol *matched = find_uelf_local_sym(uelf, uelf_file, sym); +- if (matched == NULL) { +- ERROR("Cannot find symbol '%s' in %s", sym->name, g_uelf_name); +- } +- } +- +- struct symbol *sym = uelf_file; +- list_for_each_entry_continue(sym, &uelf->symbols, list) { +- if (sym->type == STT_FILE) { +- break; // match within current file +- } +- if ((sym->bind != STB_LOCAL) || +- ((sym->type != STT_FUNC) && (sym->type != STT_OBJECT))) { +- continue; +- } +- if (is_subfunction_sym(sym)) { +- continue; +- } +- if (has_function_prefix(sym->name)) { +- continue; +- } +- if (is_discarded_sym(relf, sym)) { +- continue; +- } +- +- struct relf_symbol *matched = find_relf_local_sym(relf, relf_file, sym); +- if (matched == NULL) { +- ERROR("Cannot find symbol '%s' in %s", sym->name, g_relf_name); +- } +- if ((sym->relf_sym != NULL) && (sym->relf_sym != matched)) { +- ERROR("Found duplicated symbol '%s' in %s", sym->name, g_relf_name); +- } +- sym->relf_sym = matched; +- } +-} +- +-/* +- * Because there can be duplicate symbols in elf, we need correlate each symbol +- * from source elf to it's corresponding symbol in running elf. +- * Both the source elf and the running elf can be split on STT_FILE +- * symbols into blocks of symbols originating from a single source file. +- * We then compare local symbol lists from both blocks and store the pointer +- * to STT_FILE symbol in running elf for later using. +- */ +-static void match_local_symbols(struct upatch_elf *uelf, struct running_elf *relf) +-{ +- struct symbol *uelf_file = NULL; +- +- list_for_each_entry(uelf_file, &uelf->symbols, list) { +- if ((uelf_file->type != STT_FILE) || (uelf_file->status != CHANGED)) { +- continue; +- } +- struct relf_symbol *relf_file = find_relf_file_sym(relf, uelf_file); +- if (relf_file == NULL) { +- ERROR("Cannot find file '%s' in %s", uelf_file->name, g_relf_name); +- } +- match_file_local_symbols(uelf, relf, uelf_file, relf_file); +- } +-} +- + static void mark_file_symbols(struct upatch_elf *uelf) + { + struct symbol *curr_sym = NULL; +@@ -1040,7 +860,6 @@ int main(int argc, char **argv) + + upatch_compare_correlated_elements(&uelf_patched); + mark_file_symbols(&uelf_source); +- match_local_symbols(&uelf_source, &relf); + + include_standard_elements(&uelf_patched); + int change_count = include_changes(&uelf_patched); +-- +2.43.0 + diff --git a/0091-upatch-diff-rewrite-uelf-relf-struct.patch b/0091-upatch-diff-rewrite-uelf-relf-struct.patch new file mode 100644 index 0000000000000000000000000000000000000000..f636c9e4b17365cea294942390ad6a093093a0cc --- /dev/null +++ b/0091-upatch-diff-rewrite-uelf-relf-struct.patch @@ -0,0 +1,1192 @@ +From af7ea7faf9d9c7b25b54954634fbfe6bd875fca3 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Tue, 13 May 2025 10:02:00 +0800 +Subject: [PATCH] upatch-diff: rewrite uelf & relf struct + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 40 +++--- + upatch-diff/elf-common.c | 6 +- + upatch-diff/elf-common.h | 19 ++- + upatch-diff/elf-compare.c | 8 +- + upatch-diff/elf-compare.h | 2 +- + upatch-diff/elf-correlate.c | 22 ++- + upatch-diff/elf-correlate.h | 2 +- + upatch-diff/elf-create.c | 29 ++-- + upatch-diff/elf-create.h | 3 +- + upatch-diff/elf-debug.h | 2 +- + upatch-diff/elf-insn.c | 1 + + upatch-diff/elf-insn.h | 7 +- + upatch-diff/elf-resolve.c | 12 +- + upatch-diff/elf-resolve.h | 3 + + upatch-diff/list.h | 7 +- + upatch-diff/running-elf.c | 40 ++---- + upatch-diff/running-elf.h | 23 ++- + upatch-diff/upatch-elf.c | 232 +++++++++++++++---------------- + upatch-diff/upatch-elf.h | 138 +++++++++--------- + 19 files changed, 296 insertions(+), 300 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index b27351f..887f9a6 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -284,10 +284,10 @@ static void bundle_symbols(struct upatch_elf *uelf) + ERROR("Symbol '%s' at offset %lu of section '%s', expected 0.", + sym->name, sym->sym.st_value, sym->sec->name); + } +- sym->sec->sym = sym; ++ sym->sec->bundle_sym = sym; + /* except handler is also a kind of bundle symbol */ + } else if (sym->type == STT_SECTION && is_except_section(sym->sec)) { +- sym->sec->sym = sym; ++ sym->sec->bundle_sym = sym; + } + } + } +@@ -353,24 +353,22 @@ static void mark_file_symbols(struct upatch_elf *uelf) + static void mark_grouped_sections(struct upatch_elf *uelf) + { + struct section *groupsec; +- struct section *sec; +- unsigned int *data; +- unsigned int *end; +- + list_for_each_entry(groupsec, &uelf->sections, list) { + if (groupsec->sh.sh_type != SHT_GROUP) { + continue; + } +- data = groupsec->data->d_buf; +- end = groupsec->data->d_buf + groupsec->data->d_size; ++ ++ GElf_Word *data = groupsec->data->d_buf; ++ GElf_Word *end = groupsec->data->d_buf + groupsec->data->d_size; + data++; /* skip first flag word (e.g. GRP_COMDAT) */ ++ + while (data < end) { +- sec = find_section_by_index(&uelf->sections, *data); +- if (!sec) { +- ERROR("Group section not found"); ++ struct section *sec = find_section_by_index(&uelf->sections, (GElf_Section)*data); ++ if (sec == NULL) { ++ ERROR("Cannot find group section, index=%d", *data); + } + sec->grouped = true; +- log_debug("Marking section grouped, index: %d, name: '%s'\n", ++ log_debug("Marking grouped section, index: %d, name: '%s'\n", + sec->index, sec->name); + data++; + } +@@ -408,8 +406,8 @@ static void replace_section_syms(struct upatch_elf *uelf) + * rela->sym->sec->sym is the bundleable symbol which is + * a function or object. + */ +- if (rela->sym->sec->sym) { +- rela->sym = rela->sym->sec->sym; ++ if (rela->sym->sec->bundle_sym) { ++ rela->sym = rela->sym->sec->bundle_sym; + if (rela->sym->sym.st_value != 0) { + ERROR("Symbol offset is not zero."); + } +@@ -519,7 +517,7 @@ static void mark_ignored_sections(struct upatch_elf *uelf) + sec->base->name : sec->name; + if (strncmp(sec_name, ignored_name, name_len) == 0) { + sec->ignored = true; +- log_debug("Marking section ignored, index: %d, name: '%s'\n", ++ log_debug("Marking ignored section, index: %d, name: '%s'\n", + sec->index, sec->name); + break; + } +@@ -554,8 +552,8 @@ static void include_special_local_section(struct upatch_elf *uelf) { + sym->sec->data->d_buf = NULL; + sym->sec->data->d_size = 0; + // arm error: (.debug_info+0x...) undefined reference to `no symbol' +- if (sym->sec->secsym) { +- sym->sec->secsym->include = true; ++ if (sym->sec->sym) { ++ sym->sec->sym->include = true; + } + } + } +@@ -609,7 +607,7 @@ static void include_section(struct section *sec) + } + return; + } else { +- include_symbol(sec->secsym); ++ include_symbol(sec->sym); + include_section(sec->rela); + } + } +@@ -775,8 +773,8 @@ static void migrate_included_elements(struct upatch_elf *uelf_patched, + sec->index = 0; + + if (!is_rela_section(sec)) { +- if (sec->secsym && !sec->secsym->include) { +- sec->secsym = NULL; // break link to non-included section symbol ++ if (sec->sym && !sec->sym->include) { ++ sec->sym = NULL; // break link to non-included section symbol + } + } + } +@@ -790,7 +788,7 @@ static void migrate_included_elements(struct upatch_elf *uelf_patched, + list_del(&sym->list); + list_add_tail(&sym->list, &uelf_out->symbols); + sym->index = 0; +- sym->strip = SYMBOL_DEFAULT; ++ sym->strip = false; + + if (sym->sec && !sym->sec->include) { + sym->sec = NULL; // break link to non-included section +diff --git a/upatch-diff/elf-common.c b/upatch-diff/elf-common.c +index 3636c01..c5d8f61 100644 +--- a/upatch-diff/elf-common.c ++++ b/upatch-diff/elf-common.c +@@ -77,11 +77,11 @@ bool is_special_static_symbol(struct symbol *sym) + + if (sym->type == STT_SECTION) { + /* make sure section is bundled */ +- if (is_rela_section(sym->sec) || (sym->sec->sym == NULL)) { ++ if (is_rela_section(sym->sec) || (sym->sec->bundle_sym == NULL)) { + return false; + } + /* use bundled object object/function symbol for matching */ +- sym = sym->sec->sym; ++ sym = sym->sec->bundle_sym; + } + + if ((sym->type != STT_OBJECT) || (sym->bind != STB_LOCAL)) { +@@ -109,7 +109,7 @@ bool is_special_static_symbol(struct symbol *sym) + bool is_special_static_section(struct section *sec) + { + struct symbol *sym = is_rela_section(sec) ? +- sec->base->secsym : sec->secsym; ++ sec->base->sym : sec->sym; + return is_special_static_symbol(sym); + } + +diff --git a/upatch-diff/elf-common.h b/upatch-diff/elf-common.h +index d3dbd2f..3cebd32 100644 +--- a/upatch-diff/elf-common.h ++++ b/upatch-diff/elf-common.h +@@ -155,7 +155,7 @@ static inline bool is_symbol_ignored(struct symbol *sym) + return (sym->sec != NULL) && sym->sec->ignored; + } + +-static inline struct symbol *find_symbol_by_index(struct list_head *list, unsigned int index) ++static inline struct symbol *find_symbol_by_index(struct list_head *list, GElf_Word index) + { + struct symbol *sym; + +@@ -181,7 +181,7 @@ static inline struct symbol *find_symbol_by_name(struct list_head *list, const c + return NULL; + } + +-static inline struct section *find_section_by_index(struct list_head *list, unsigned int index) ++static inline struct section *find_section_by_index(struct list_head *list, GElf_Section index) + { + struct section *sec; + +@@ -207,6 +207,19 @@ static inline struct section *find_section_by_name(struct list_head *list, const + return NULL; + } + ++static inline struct section *find_section_by_type(struct list_head *list, GElf_Word type) ++{ ++ struct section *sec; ++ ++ list_for_each_entry(sec, list, list) { ++ if (sec->sh.sh_type == type) { ++ return sec; ++ } ++ } ++ ++ return NULL; ++} ++ + static inline bool has_digit_tail(char *tail) + { + if (*tail != '.') { +@@ -238,7 +251,7 @@ static inline char *section_function_name(struct section *sec) + if (is_rela_section(sec)) { + sec = sec->base; + } +- return sec->sym ? sec->sym->name : sec->name; ++ return sec->bundle_sym ? sec->bundle_sym->name : sec->name; + } + + static inline char *status_str(enum status status) +diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c +index 97daa0b..eb8bdc1 100644 +--- a/upatch-diff/elf-compare.c ++++ b/upatch-diff/elf-compare.c +@@ -196,12 +196,12 @@ static void update_section_status(struct section *sec, enum status status) + sec->twin->status = status; + } + if (is_rela_section(sec)) { +- if ((sec->base != NULL) && (sec->base->sym != NULL) && status != SAME) { +- sec->base->sym->status = status; ++ if ((sec->base != NULL) && (sec->base->bundle_sym != NULL) && status != SAME) { ++ sec->base->bundle_sym->status = status; + } + } else { +- if (sec->sym != NULL) { +- sec->sym->status = status; ++ if (sec->bundle_sym != NULL) { ++ sec->bundle_sym->status = status; + } + } + } +diff --git a/upatch-diff/elf-compare.h b/upatch-diff/elf-compare.h +index 8ec1655..5202fb0 100644 +--- a/upatch-diff/elf-compare.h ++++ b/upatch-diff/elf-compare.h +@@ -25,7 +25,7 @@ + #ifndef __UPATCH_ELF_COMPARE_H_ + #define __UPATCH_ELF_COMPARE_H_ + +-#include "upatch-elf.h" ++struct upatch_elf; + + void upatch_compare_symbols(struct upatch_elf *); + +diff --git a/upatch-diff/elf-correlate.c b/upatch-diff/elf-correlate.c +index d5e76f6..dcf3cfa 100644 +--- a/upatch-diff/elf-correlate.c ++++ b/upatch-diff/elf-correlate.c +@@ -37,10 +37,6 @@ static void correlate_symbol(struct symbol *sym_orig, + log_debug("renaming symbol %s to %s\n", + sym_patched->name, sym_orig->name); + sym_patched->name = sym_orig->name; +- sym_patched->name_source = DATA_SOURCE_REF; +- } +- if (sym_orig->relf_sym && !sym_patched->relf_sym) { +- sym_patched->relf_sym = sym_orig->relf_sym; + } + } + +@@ -133,12 +129,12 @@ static void correlate_section(struct section *sec_orig, + } else if (sec_orig->rela && sec_patched->rela) { + correlate_section_impl(sec_orig->rela, sec_patched->rela); + } +- if (sec_orig->secsym && sec_patched->secsym) { +- correlate_symbol(sec_orig->secsym, sec_patched->secsym); +- } +- if (sec_orig->sym) { ++ if (sec_orig->sym && sec_patched->sym) { + correlate_symbol(sec_orig->sym, sec_patched->sym); + } ++ if (sec_orig->bundle_sym) { ++ correlate_symbol(sec_orig->bundle_sym, sec_patched->bundle_sym); ++ } + } + + void upatch_correlate_sections(struct upatch_elf *uelf_source, +@@ -382,11 +378,11 @@ void upatch_correlate_static_local_variables(struct upatch_elf *uelf_source, + uncorrelate_symbol(sym); + } + +- bundled = (sym == sym->sec->sym) ? 1 : 0; ++ bundled = (sym == sym->sec->bundle_sym) ? 1 : 0; + if (bundled && sym->sec->twin) { + uncorrelate_section(sym->sec); +- if (sym->sec->secsym) { +- uncorrelate_symbol(sym->sec->secsym); ++ if (sym->sec->sym) { ++ uncorrelate_symbol(sym->sec->sym); + } + if (sym->sec->rela) { + // uncorrelate relocation section which not equals to reference +@@ -418,7 +414,7 @@ void upatch_correlate_static_local_variables(struct upatch_elf *uelf_source, + continue; + } + +- bundled = (sym == sym->sec->sym) ? 1 : 0; ++ bundled = (sym == sym->sec->bundle_sym) ? 1 : 0; + if (bundled && sym->sec == relasec->base) { + /* + * TODO: +@@ -439,7 +435,7 @@ void upatch_correlate_static_local_variables(struct upatch_elf *uelf_source, + continue; + } + +- patched_bundled = (patched_sym == patched_sym->sec->sym) ? 1 : 0; ++ patched_bundled = (patched_sym == patched_sym->sec->bundle_sym) ? 1 : 0; + if (bundled != patched_bundled) { + ERROR("bundle mismatch for symbol %s", sym->name); + } +diff --git a/upatch-diff/elf-correlate.h b/upatch-diff/elf-correlate.h +index 820d07a..2e44302 100644 +--- a/upatch-diff/elf-correlate.h ++++ b/upatch-diff/elf-correlate.h +@@ -25,7 +25,7 @@ + #ifndef __UPATCH_ELF_CORRELATE_H_ + #define __UPATCH_ELF_CORRELATE_H_ + +-#include "upatch-elf.h" ++struct upatch_elf; + + void upatch_correlate_sections(struct upatch_elf *, struct upatch_elf *); + +diff --git a/upatch-diff/elf-create.c b/upatch-diff/elf-create.c +index eea1315..c131029 100644 +--- a/upatch-diff/elf-create.c ++++ b/upatch-diff/elf-create.c +@@ -34,6 +34,8 @@ + #include "elf-create.h" + #include "upatch-patch.h" + #include "upatch-dynrela.h" ++#include "upatch-elf.h" ++#include "running-elf.h" + + /* create text and relocation sections */ + static struct section *create_section_pair(struct upatch_elf *uelf, char *name, +@@ -148,7 +150,6 @@ void upatch_create_patches_sections(struct upatch_elf *uelf, + + struct upatch_patch_func *funcs; + struct rela *rela; +- struct lookup_result symbol; + + unsigned int nr = 0; + unsigned int index = 0; +@@ -180,24 +181,26 @@ void upatch_create_patches_sections(struct upatch_elf *uelf, + if (sym->type != STT_FUNC || sym->status != CHANGED || sym->parent) { + continue; + } +- if (!lookup_relf(relf, sym, &symbol)) { ++ ++ struct relf_symbol *symbol = lookup_relf(relf, sym); ++ if (symbol == NULL) { + ERROR("Cannot find symbol '%s' in %s", sym->name, g_relf_name); + } +- if (sym->bind == STB_LOCAL && symbol.global) { ++ if ((sym->bind == STB_LOCAL) && (symbol->bind != STB_LOCAL)) { + ERROR("Cannot find local symbol '%s' in symbol table.", sym->name); + } +- log_debug("lookup for %s: symbol name %s sympos=%lu size=%lu.\n", +- sym->name, symbol.symbol->name, symbol.sympos, symbol.symbol->size); ++ log_debug("lookup for %s: symbol name %s sympos=%u size=%lu.\n", ++ sym->name, symbol->name, symbol->index, symbol->size); + + /* ATTENTION: kpatch convert global symbols to local symbols here. */ +- if (symbol.symbol->addr < text_offset) { ++ if (symbol->addr < text_offset) { + ERROR("Text section offset 0x%lx overflow, sym_addr=0x%lx", +- text_offset, symbol.symbol->addr); ++ text_offset, symbol->addr); + } +- funcs[index].old_addr = symbol.symbol->addr - text_offset; +- funcs[index].old_size = symbol.symbol->size; ++ funcs[index].old_addr = symbol->addr - text_offset; ++ funcs[index].old_size = symbol->size; + funcs[index].new_size = sym->sym.st_size; +- funcs[index].sympos = symbol.sympos; ++ funcs[index].sympos = symbol->index; + + log_debug("change func %s from 0x%lx.\n", + sym->name, funcs[index].old_addr); +@@ -300,7 +303,7 @@ void upatch_strip_unneeded_syms(struct upatch_elf *uelf) + struct symbol *sym, *sym_safe; + + list_for_each_entry_safe(sym, sym_safe, &uelf->symbols, list) { +- if (sym->strip == SYMBOL_STRIP) { ++ if (sym->strip) { + list_del(&sym->list); + free(sym); + } +@@ -311,7 +314,7 @@ void upatch_reindex_elements(struct upatch_elf *uelf) + { + struct section *sec; + struct symbol *sym; +- unsigned int index; ++ GElf_Section index; + + index = 1; + list_for_each_entry(sec, &uelf->sections, list) { +@@ -324,7 +327,7 @@ void upatch_reindex_elements(struct upatch_elf *uelf) + sym->index = index; + index++; + if (sym->sec) { +- sym->sym.st_shndx = (unsigned short)sym->sec->index; ++ sym->sym.st_shndx = sym->sec->index; + } else if (sym->sym.st_shndx != SHN_ABS) { + sym->sym.st_shndx = SHN_UNDEF; + } +diff --git a/upatch-diff/elf-create.h b/upatch-diff/elf-create.h +index 0c76a46..c0f4fa5 100644 +--- a/upatch-diff/elf-create.h ++++ b/upatch-diff/elf-create.h +@@ -25,7 +25,8 @@ + #ifndef __UPATCH_CREATE_H_ + #define __UPATCH_CREATE_H_ + +-#include "upatch-elf.h" ++struct upatch_elf; ++struct running_elf; + + void upatch_create_strings_elements(struct upatch_elf *); + +diff --git a/upatch-diff/elf-debug.h b/upatch-diff/elf-debug.h +index 09122f6..c196ed7 100644 +--- a/upatch-diff/elf-debug.h ++++ b/upatch-diff/elf-debug.h +@@ -25,7 +25,7 @@ + #ifndef __UPATCH_ELF_DEBUG_H_ + #define __UPATCH_ELF_DEBUG_H_ + +-#include "upatch-elf.h" ++struct upatch_elf; + + void upatch_print_correlation(struct upatch_elf *uelf); + void upatch_print_changes(struct upatch_elf *uelf); +diff --git a/upatch-diff/elf-insn.c b/upatch-diff/elf-insn.c +index 8fcfc39..6fabd88 100644 +--- a/upatch-diff/elf-insn.c ++++ b/upatch-diff/elf-insn.c +@@ -25,6 +25,7 @@ + + #include + ++#include "insn/asm/insn.h" + #include "elf-common.h" + #include "elf-insn.h" + +diff --git a/upatch-diff/elf-insn.h b/upatch-diff/elf-insn.h +index f64ebe1..ac48ad0 100644 +--- a/upatch-diff/elf-insn.h ++++ b/upatch-diff/elf-insn.h +@@ -26,8 +26,11 @@ + #ifndef __UPATCH_INSN_H_ + #define __UPATCH_INSN_H_ + +-#include "asm/insn.h" +-#include "upatch-elf.h" ++#include ++ ++struct section; ++struct rela; ++struct insn; + + #define ARM64_INSTR_LEN 4 + +diff --git a/upatch-diff/elf-resolve.c b/upatch-diff/elf-resolve.c +index 67ab069..2375b73 100755 +--- a/upatch-diff/elf-resolve.c ++++ b/upatch-diff/elf-resolve.c +@@ -20,9 +20,10 @@ + * 02110-1301, USA. + */ + +- ++#include + #include + ++#include "upatch-elf.h" + #include "running-elf.h" + #include "upatch-patch.h" + +@@ -30,16 +31,15 @@ + void upatch_partly_resolve(struct upatch_elf *uelf, struct running_elf *relf) + { + struct symbol *sym; +- struct lookup_result symbol; +- + list_for_each_entry(sym, &uelf->symbols, list) { + if (sym->sym.st_other & SYM_OTHER) { +- if (!lookup_relf(relf, sym, &symbol)) { ++ struct relf_symbol *symbol = lookup_relf(relf, sym); ++ if (symbol == NULL) { + continue; + } + /* keep it undefined for link purpose */ +- sym->sym.st_value = symbol.symbol->addr; +- sym->sym.st_size = symbol.symbol->size; ++ sym->sym.st_value = symbol->addr; ++ sym->sym.st_size = symbol->size; + } + } + } +diff --git a/upatch-diff/elf-resolve.h b/upatch-diff/elf-resolve.h +index 05b4b35..92a1012 100755 +--- a/upatch-diff/elf-resolve.h ++++ b/upatch-diff/elf-resolve.h +@@ -23,6 +23,9 @@ + #ifndef __UPATCH_RESOLVE_H_ + #define __UPATCH_RESOLVE_H_ + ++struct upatch_elf; ++struct running_elf; ++ + void upatch_partly_resolve(struct upatch_elf *, struct running_elf *); + + #endif /* __UPATCH_RESOLVE_H_ */ +diff --git a/upatch-diff/list.h b/upatch-diff/list.h +index b56a2b0..0b09108 100644 +--- a/upatch-diff/list.h ++++ b/upatch-diff/list.h +@@ -28,6 +28,8 @@ + #ifndef __UPATCH_LIST_H_ + #define __UPATCH_LIST_H_ + ++#include ++ + /* + * These are non-NULL pointers that will result in page faults + * under normal circumstances, used to verify that nobody uses +@@ -36,11 +38,6 @@ + #define LIST_POISON1 ((void *) 0x00100100) + #define LIST_POISON2 ((void *) 0x00200200) + +-/** +- * Get offset of a member +- */ +-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +- + /** + * Casts a member of a structure out to the containing structure + * @param ptr the pointer to the member. +diff --git a/upatch-diff/running-elf.c b/upatch-diff/running-elf.c +index db44cb4..90969e5 100644 +--- a/upatch-diff/running-elf.c ++++ b/upatch-diff/running-elf.c +@@ -32,6 +32,7 @@ + #include + #include + ++#include "upatch-elf.h" + #include "running-elf.h" + #include "log.h" + +@@ -75,14 +76,14 @@ void relf_open(struct running_elf *relf, const char *name) + if (!data) { + ERROR("Failed to read file '%s' section data, %s", name, elf_errmsg(0)); + } +- relf->symbol_count = (int)(shdr.sh_size / shdr.sh_entsize); ++ relf->symbol_count = (GElf_Word)(shdr.sh_size / shdr.sh_entsize); + relf->symbols = calloc((size_t)relf->symbol_count, sizeof(struct relf_symbol)); + if (!relf->symbols) { + ERROR("Failed to alloc memory, %s", strerror(errno)); + } + +- for (int i = 0; i < relf->symbol_count; i++) { +- if (!gelf_getsym(data, i, &sym)) { ++ for (GElf_Word i = 0; i < relf->symbol_count; i++) { ++ if (!gelf_getsym(data, (int)i, &sym)) { + ERROR("Failed to read file '%s' symbol, index=%d, %s", + name, i, elf_errmsg(0)); + } +@@ -119,37 +120,26 @@ void relf_close(struct running_elf *relf) + relf->fd = -1; + } + +-bool lookup_relf(struct running_elf *relf, struct symbol *lookup_sym, +- struct lookup_result *result) ++struct relf_symbol* lookup_relf(struct running_elf *relf, struct symbol *sym) + { +- struct relf_symbol *symbol = NULL; ++ struct relf_symbol *result = NULL; + +- log_debug("looking up symbol '%s'\n", lookup_sym->name); +- memset(result, 0, sizeof(*result)); ++ for (GElf_Word i = 0; i < relf->symbol_count; i++) { ++ struct relf_symbol *symbol = &relf->symbols[i]; + +- for (int i = 0; i < relf->symbol_count; i++) { +- symbol = &relf->symbols[i]; +- +- if (result->symbol != NULL && symbol->type == STT_FILE) { ++ if ((result != NULL) && (symbol->type == STT_FILE)) { + break; + } +- if (strcmp(symbol->name, lookup_sym->name) != 0 || +- symbol->bind != lookup_sym->bind) { ++ if ((strcmp(symbol->name, sym->name) != 0) || ++ (symbol->bind != sym->bind)) { + continue; + } +- +- if ((result->symbol != NULL) && +- (result->symbol->bind == symbol->bind)) { +- ERROR("Found duplicate symbol '%s' in %s", +- lookup_sym->name, g_relf_name); ++ if ((result != NULL) && (result->bind == symbol->bind)) { ++ ERROR("Found duplicate symbol '%s' in %s", sym->name, g_relf_name); + } + +- result->symbol = symbol; +- result->sympos = (unsigned long)i; +- result->global = +- ((symbol->bind == STB_GLOBAL) || (symbol->bind == STB_WEAK)); +- log_debug("found symbol '%s'\n", lookup_sym->name); ++ result = symbol; + } + +- return (result->symbol != NULL); ++ return result; + } +diff --git a/upatch-diff/running-elf.h b/upatch-diff/running-elf.h +index ae05d83..24e9326 100644 +--- a/upatch-diff/running-elf.h ++++ b/upatch-diff/running-elf.h +@@ -30,36 +30,29 @@ + #include + #include + +-#include "upatch-elf.h" +- + struct symbol; + + struct relf_symbol { +- int index; ++ GElf_Word index; + char *name; +- unsigned char type, bind; +- unsigned int shndx; +- unsigned long addr; +- unsigned long size; ++ unsigned char type; ++ unsigned char bind; ++ GElf_Section shndx; ++ GElf_Addr addr; ++ GElf_Xword size; + }; + + struct running_elf { + int fd; + Elf *elf; + struct relf_symbol *symbols; +- int symbol_count; ++ GElf_Word symbol_count; + bool is_exec; + }; + +-struct lookup_result { +- struct relf_symbol *symbol; +- unsigned long sympos; +- bool global; +-}; +- + void relf_open(struct running_elf *relf, const char *name); + void relf_close(struct running_elf *relf); + +-bool lookup_relf(struct running_elf *, struct symbol *, struct lookup_result *); ++struct relf_symbol* lookup_relf(struct running_elf *relf, struct symbol *sym); + + #endif +diff --git a/upatch-diff/upatch-elf.c b/upatch-diff/upatch-elf.c +index 81567f5..c21b6ec 100644 +--- a/upatch-diff/upatch-elf.c ++++ b/upatch-diff/upatch-elf.c +@@ -40,180 +40,142 @@ + + static void create_section_list(struct upatch_elf *uelf) + { +- size_t shstrndx; +- size_t sections_nr; +- +- struct section *sec; +- Elf_Scn *scn = NULL; +- +- if (elf_getshdrnum(uelf->elf, §ions_nr)) { +- ERROR("elf_getshdrnum with error %s", elf_errmsg(0)); ++ size_t shstrndx = 0; ++ if (elf_getshdrstrndx(uelf->elf, &shstrndx) != 0) { ++ ERROR("Failed to get section header string index"); + } + +- sections_nr--; ++ Elf_Scn *scn = elf_nextscn(uelf->elf, NULL); ++ while (scn != NULL) { ++ GElf_Section index = (GElf_Section)elf_ndxscn(scn); ++ struct section *sec = NULL; + +- if (elf_getshdrstrndx(uelf->elf, &shstrndx)) { +- ERROR("elf_getshdrstrndx with error %s", elf_errmsg(0)); +- } +- +- while (sections_nr--) { + ALLOC_LINK(sec, &uelf->sections); +- +- scn = elf_nextscn(uelf->elf, scn); +- if (!scn) { +- ERROR("elf_nextscn with error %s", elf_errmsg(0)); +- } +- if (!gelf_getshdr(scn, &sec->sh)) { +- ERROR("gelf_getshdr with error %s", elf_errmsg(0)); ++ if (gelf_getshdr(scn, &sec->sh) == NULL) { ++ ERROR("Failed to parse section, index=%d", index); + } + ++ sec->index = (GElf_Section)index; + sec->name = elf_strptr(uelf->elf, shstrndx, sec->sh.sh_name); +- if (!sec->name) { +- ERROR("elf_strptr with error %s", elf_errmsg(0)); ++ if (sec->name == NULL) { ++ ERROR("Failed to get section name, index=%d", index); + } +- + sec->data = elf_getdata(scn, NULL); +- if (!sec->data) { +- ERROR("elf_getdata with error %s", elf_errmsg(0)); ++ if (sec->data == NULL) { ++ ERROR("Failed to get section '%s' data, index=%d", ++ sec->name, index); + } + +- sec->name_source = DATA_SOURCE_ELF; +- sec->data_source = DATA_SOURCE_ELF; +- sec->dbuf_source = DATA_SOURCE_ELF; ++ sec->name_source = DATA_SOURCE_REF; ++ sec->data_source = DATA_SOURCE_REF; ++ sec->dbuf_source = DATA_SOURCE_REF; + +- sec->index = (unsigned int)elf_ndxscn(scn); +- /* found extended section header */ +- if (sec->sh.sh_type == SHT_SYMTAB_SHNDX) { +- uelf->symtab_shndx = sec->data; /* correct ? */ +- } +- } ++ INIT_LIST_HEAD(&sec->relas); + +- if (elf_nextscn(uelf->elf, scn)) { +- ERROR("elf_nextscn with error %s", elf_errmsg(0)); ++ scn = elf_nextscn(uelf->elf, scn); + } + } + + static void create_symbol_list(struct upatch_elf *uelf) + { +- struct section *symtab; +- Elf32_Word shndx; +- +- unsigned int symbols_nr; +- unsigned int index = 0; +- struct symbol *sym; +- +- /* consider type first */ +- symtab = find_section_by_name(&uelf->sections, ".symtab"); +- if (!symtab) { +- ERROR("can't find symbol table"); ++ struct section *symtab = find_section_by_type(&uelf->sections, SHT_SYMTAB); ++ if (symtab == NULL) { ++ ERROR("Cannot find symbol table"); + } + +- symbols_nr = (unsigned int)(symtab->sh.sh_size / symtab->sh.sh_entsize); ++ GElf_Word count = (GElf_Word)(symtab->sh.sh_size / symtab->sh.sh_entsize); ++ for (GElf_Word i = 0; i < count; i++) { ++ struct symbol *sym = NULL; + +- while (symbols_nr--) { + ALLOC_LINK(sym, &uelf->symbols); +- INIT_LIST_HEAD(&sym->children); +- +- sym->index = index; +- if (!gelf_getsym(symtab->data, (int)index, &sym->sym)) { +- ERROR("gelf_getsym with error %s", elf_errmsg(0)); ++ if (gelf_getsym(symtab->data, (int)i, &sym->sym) == NULL) { ++ ERROR("Failed to parse symbol, index=%d", i); + } + +- index++; +- ++ sym->index = i; + sym->name = elf_strptr(uelf->elf, symtab->sh.sh_link, sym->sym.st_name); +- if (!sym->name) { +- ERROR("elf_strptr with error %s", elf_errmsg(0)); ++ if (sym->name == NULL) { ++ ERROR("Failed to get symbol name, index=%d", i); + } + +- sym->type = GELF_ST_TYPE(sym->sym.st_info); +- sym->bind = GELF_ST_BIND(sym->sym.st_info); ++ sym->name_source = DATA_SOURCE_REF; + +- shndx = sym->sym.st_shndx; +- /* releated section located in extended header */ +- if (shndx == SHN_XINDEX && +- !gelf_getsymshndx(symtab->data, uelf->symtab_shndx, +- (int)sym->index, &sym->sym, &shndx)) { +- ERROR("gelf_getsymshndx with error %s", elf_errmsg(0)); +- } +- if (sym->sym.st_shndx == SHN_XINDEX || +- (sym->sym.st_shndx > SHN_UNDEF && +- sym->sym.st_shndx < SHN_LORESERVE)) { ++ sym->bind = GELF_ST_BIND(sym->sym.st_info); ++ sym->type = GELF_ST_TYPE(sym->sym.st_info); ++ GElf_Section shndx = sym->sym.st_shndx; ++ if ((sym->sym.st_shndx > SHN_UNDEF) && ++ (sym->sym.st_shndx < SHN_LORESERVE)) { + sym->sec = find_section_by_index(&uelf->sections, shndx); +- if (!sym->sec) { +- ERROR("no releated section found for symbol %s\n", sym->name); ++ if (sym->sec == NULL) { ++ ERROR("Failed to find symbol '%s' section, index=%d, shndx=%d", ++ sym->name, i, shndx); + } +- +- /* this symbol is releated with a section */ + if (sym->type == STT_SECTION) { +- /* secsym must be the bundleable symbol */ +- sym->sec->secsym = sym; ++ /* sym must be the bundleable symbol */ ++ sym->sec->sym = sym; + /* use section name as symbol name */ + sym->name = sym->sec->name; + } + } ++ ++ INIT_LIST_HEAD(&sym->children); ++ INIT_LIST_HEAD(&sym->subfunction_node); + } + } + +-static void create_rela_list(struct upatch_elf *uelf, struct section *relasec) ++static void create_rela_list(struct upatch_elf *uelf, struct section *sec) + { +- struct rela *rela; +- unsigned long rela_nr; +- +- unsigned int symndx; +- int index = 0; +- +- INIT_LIST_HEAD(&relasec->relas); +- + /* for relocation sections, sh_info is the index which these info apply */ +- relasec->base = find_section_by_index(&uelf->sections, relasec->sh.sh_info); +- if (!relasec->base) { +- ERROR("no base section found for relocation section %s", relasec->name); ++ sec->base = (struct section *)sec->info; ++ if (sec->base == NULL) { ++ ERROR("Cannot find section '%s' base section, index=%d", ++ sec->name, sec->index); + } +- relasec->base->rela = relasec; +- rela_nr = relasec->sh.sh_size / relasec->sh.sh_entsize; ++ sec->base->rela = sec; + +- while (rela_nr--) { +- ALLOC_LINK(rela, &relasec->relas); ++ GElf_Word count = (GElf_Word)(sec->sh.sh_size / sec->sh.sh_entsize); ++ for (GElf_Word i = 0; i < count; i++) { ++ struct rela *rela = NULL; + +- /* use index because we need to keep the order of rela */ +- if (!gelf_getrela(relasec->data, index, &rela->rela)) { +- ERROR("gelf_getrela with error %s", elf_errmsg(0)); ++ ALLOC_LINK(rela, &sec->relas); ++ if (gelf_getrela(sec->data, (int)i, &rela->rela) == NULL) { ++ ERROR("Failed to parse rela, index=%d", i); + } +- index++; + +- rela->type = GELF_R_TYPE(rela->rela.r_info); +- rela->addend = rela->rela.r_addend; +- rela->offset = (unsigned int)rela->rela.r_offset; +- symndx = (unsigned int)GELF_R_SYM(rela->rela.r_info); ++ GElf_Word symndx = (GElf_Word)GELF_R_SYM(rela->rela.r_info); + rela->sym = find_symbol_by_index(&uelf->symbols, symndx); +- if (!rela->sym) { +- ERROR("no rela entry symbol found\n"); ++ if (rela->sym == NULL) { ++ ERROR("Cannot find rela symbol, index=%d, symndx=%d", i, symndx); + } ++ rela->type = GELF_R_TYPE(rela->rela.r_info); ++ rela->addend = rela->rela.r_addend; ++ rela->offset = rela->rela.r_offset; ++ ++ if (is_string_section(rela->sym->sec)) { ++ void *data = rela->sym->sec->data->d_buf; ++ GElf_Addr addr = rela->sym->sym.st_value; ++ long offset = rela_target_offset(uelf, sec, rela); + +- if (rela->sym->sec && is_string_section(rela->sym->sec)) { +- rela->string = rela->sym->sec->data->d_buf + +- rela->sym->sym.st_value + +- rela_target_offset(uelf, relasec, rela); +- if (!rela->string) { +- ERROR("could not lookup rela string for %s+%ld", ++ rela->string = data + addr + offset; ++ if (rela->string == NULL) { ++ ERROR("Cannot find rela string %s+%ld", + rela->sym->name, rela->addend); + } + } + } + } + +-static void destroy_rela_list(struct section *relasec) ++static void destroy_rela_list(struct section *sec) + { + struct rela *rela = NULL; +- struct rela *saferela = NULL; ++ struct rela *safe = NULL; + +- list_for_each_entry_safe(rela, saferela, &relasec->relas, list) { ++ list_for_each_entry_safe(rela, safe, &sec->relas, list) { + list_del(&rela->list); + free(rela); + } + +- INIT_LIST_HEAD(&relasec->relas); ++ INIT_LIST_HEAD(&sec->relas); + } + + static void destroy_section_list(struct upatch_elf *uelf) +@@ -283,6 +245,41 @@ static void destroy_string_list(struct upatch_elf *uelf) + INIT_LIST_HEAD(&uelf->strings); + } + ++static void parse_section_metadata(struct upatch_elf *uelf) ++{ ++ struct section *sec; ++ list_for_each_entry(sec, &uelf->sections, list) { ++ /* find sh_link */ ++ if (sec->sh.sh_link != SHN_UNDEF) { ++ sec->link = find_section_by_index(&uelf->sections, ++ (GElf_Section)sec->sh.sh_link); ++ if (sec->link == NULL) { ++ ERROR("Cannot find '%s' link section, sh_link=%d", ++ sec->name, sec->sh.sh_link); ++ } ++ } ++ /* find sh_info */ ++ if ((sec->sh.sh_type == SHT_REL) || (sec->sh.sh_type == SHT_RELA)) { ++ sec->info = find_section_by_index(&uelf->sections, ++ (GElf_Section)sec->sh.sh_info); ++ if (sec->link == NULL) { ++ ERROR("Cannot find '%s' info section, sh_info=%d", ++ sec->name, sec->sh.sh_link); ++ } ++ } else if (sec->sh.sh_type == SHT_GROUP) { ++ sec->info = find_symbol_by_index(&uelf->symbols, sec->sh.sh_info); ++ if (sec->link == NULL) { ++ ERROR("Cannot find '%s' info symbol, sh_info=%d", ++ sec->name, sec->sh.sh_link); ++ } ++ } ++ /* handle rela section */ ++ if (sec->sh.sh_type == SHT_RELA) { ++ create_rela_list(uelf, sec); ++ } ++ } ++} ++ + void uelf_open(struct upatch_elf *uelf, const char *name) + { + GElf_Ehdr ehdr; +@@ -330,13 +327,7 @@ void uelf_open(struct upatch_elf *uelf, const char *name) + + create_section_list(uelf); + create_symbol_list(uelf); +- +- struct section *sec; +- list_for_each_entry(sec, &uelf->sections, list) { +- if (is_rela_section(sec)) { +- create_rela_list(uelf, sec); +- } +- } ++ parse_section_metadata(uelf); + } + + void uelf_close(struct upatch_elf *uelf) +@@ -356,5 +347,4 @@ void uelf_close(struct upatch_elf *uelf) + } + uelf->elf = NULL; + uelf->fd = -1; +- uelf->symtab_shndx = NULL; + } +diff --git a/upatch-diff/upatch-elf.h b/upatch-diff/upatch-elf.h +index eeb7fb2..858cfa9 100644 +--- a/upatch-diff/upatch-elf.h ++++ b/upatch-diff/upatch-elf.h +@@ -26,11 +26,10 @@ + #ifndef __UPATCH_ELF_H_ + #define __UPATCH_ELF_H_ + +-#include + #include ++#include + + #include "list.h" +-#include "running-elf.h" + + extern char *g_relf_name; + +@@ -39,103 +38,112 @@ struct section; + struct rela; + struct symbol; + ++enum architecture { ++ X86_64 = 0x1 << 0, ++ AARCH64 = 0x1 << 1, ++}; ++ + enum data_source { +- DATA_SOURCE_ELF, + DATA_SOURCE_REF, + DATA_SOURCE_ALLOC, + }; + + enum status { +- NEW, ++ SAME, + CHANGED, +- SAME +-}; +- +-enum symbol_strip { +- SYMBOL_DEFAULT, +- SYMBOL_USED, +- SYMBOL_STRIP, ++ NEW, + }; + +-struct string { +- struct list_head list; +- char *name; ++struct upatch_elf { ++ int fd; ++ Elf *elf; ++ enum architecture arch; ++ struct list_head sections; ++ struct list_head symbols; ++ struct list_head strings; + }; + + struct section { + struct list_head list; +- struct section *twin; ++ GElf_Shdr sh; ++ ++ GElf_Section index; + char *name; + Elf_Data *data; ++ ++ /* data source */ + enum data_source name_source; + enum data_source data_source; + enum data_source dbuf_source; +- GElf_Shdr sh; +- bool ignored; +- bool include; +- bool grouped; +- unsigned int index; +- enum status status; +- union { +- // section with relocation information +- struct { +- struct section *base; +- struct list_head relas; +- }; +- // other function or data section +- struct { +- struct section *rela; +- struct symbol *sym; +- struct symbol *secsym; +- }; +- }; +-}; + +-struct rela { +- struct list_head list; +- GElf_Rela rela; ++ /* section info */ ++ struct section *link; ++ void *info; ++ ++ /* symbol reference */ + struct symbol *sym; +- unsigned int type; +- unsigned long offset; +- long addend; +- char *string; +- bool need_dynrela; ++ struct symbol *bundle_sym; ++ ++ /* reloc reference */ ++ struct section *base; ++ struct section *rela; ++ struct list_head relas; ++ ++ /* diff metadata */ ++ struct section *twin; ++ enum status status; ++ bool grouped; ++ bool ignored; ++ bool include; + }; + + struct symbol { + struct list_head list; +- struct symbol *twin; +- struct symbol *parent; +- struct list_head children; +- struct list_head subfunction_node; +- struct section *sec; + GElf_Sym sym; ++ ++ GElf_Word index; + char *name; ++ ++ /* data source */ + enum data_source name_source; +- struct relf_symbol *relf_sym; +- unsigned int index; ++ ++ /* symbol info */ + unsigned char bind; + unsigned char type; ++ ++ /* section reference */ ++ struct section *sec; ++ ++ /* subfunction reference */ ++ struct symbol *parent; ++ struct list_head children; ++ struct list_head subfunction_node; ++ ++ /* diff metadata */ ++ struct symbol *twin; + enum status status; +- union { +- bool include; /* used in the patched elf */ +- enum symbol_strip strip; /* used in the output elf */ +- }; ++ bool include; /* used in the patched elf */ ++ bool strip; /* used in the output elf */ + }; + +-enum architecture { +- X86_64 = 0x1 << 0, +- AARCH64 = 0x1 << 1, ++struct rela { ++ struct list_head list; ++ GElf_Rela rela; ++ ++ /* symbol reference */ ++ struct symbol *sym; ++ ++ /* rela info */ ++ GElf_Word type; ++ GElf_Off offset; ++ GElf_Sxword addend; ++ ++ char *string; + }; + +-struct upatch_elf { +- Elf *elf; +- enum architecture arch; +- struct list_head sections; +- struct list_head symbols; +- struct list_head strings; +- Elf_Data *symtab_shndx; +- int fd; ++struct string { ++ struct list_head list; ++ char *name; + }; + + void uelf_open(struct upatch_elf *uelf, const char *name); +-- +2.43.0 + diff --git a/0092-upatch-diff-fix-access-freed-section-data-issue.patch b/0092-upatch-diff-fix-access-freed-section-data-issue.patch new file mode 100644 index 0000000000000000000000000000000000000000..227610f8166b0b99ed3d44d30b674cd8605c58dc --- /dev/null +++ b/0092-upatch-diff-fix-access-freed-section-data-issue.patch @@ -0,0 +1,34 @@ +From feb2f1ba319cd6fb4d54bea622cb49b0f032014e Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 14 May 2025 15:02:23 +0800 +Subject: [PATCH] upatch-diff: fix access freed section data issue + + Some sections in output uelf may reference other +uelf section, which would be closed at very last. + This would cause accessing freed section data while +closing output uelf. We need to close it at first. + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 887f9a6..9e4504e 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -909,9 +909,9 @@ int main(int argc, char **argv) + upatch_write_output_elf(&uelf_out, uelf_patched.elf, args.output_obj, 0664); + log_normal("Done\n"); + +- uelf_close(&uelf_source); +- uelf_close(&uelf_patched); + uelf_close(&uelf_out); ++ uelf_close(&uelf_patched); ++ uelf_close(&uelf_source); + relf_close(&relf); + + fflush(stdout); +-- +2.43.0 + diff --git a/0093-syscared-fix-kernel-compatibility-check-is-not-worki.patch b/0093-syscared-fix-kernel-compatibility-check-is-not-worki.patch new file mode 100644 index 0000000000000000000000000000000000000000..75a351c1c6b7e2cf8a0ae4e072178b98de1425d7 --- /dev/null +++ b/0093-syscared-fix-kernel-compatibility-check-is-not-worki.patch @@ -0,0 +1,26 @@ +From 234a6f213bd9faeac7c4b5a94b449d87b5af9c2f Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Sun, 27 Apr 2025 19:40:06 +0800 +Subject: [PATCH] syscared: fix kernel compatibility check is not working issue + +Signed-off-by: renoseven +--- + syscared/src/patch/driver/kpatch/mod.rs | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/syscared/src/patch/driver/kpatch/mod.rs b/syscared/src/patch/driver/kpatch/mod.rs +index bdcdd4c..ba177ac 100644 +--- a/syscared/src/patch/driver/kpatch/mod.rs ++++ b/syscared/src/patch/driver/kpatch/mod.rs +@@ -134,7 +134,7 @@ impl KernelPatchDriver { + debug!("Patch target: '{}'", patch_target); + debug!("Current kernel: '{}'", current_kernel.to_string_lossy()); + +- if !patch_target.starts_with("KERNEL_NAME_PREFIX") { ++ if !patch_target.starts_with(KERNEL_NAME_PREFIX) { + return Ok(()); + } + ensure!( +-- +2.43.0 + diff --git a/0094-syscare-build-add-debug-option-to-kpatch-build.patch b/0094-syscare-build-add-debug-option-to-kpatch-build.patch new file mode 100644 index 0000000000000000000000000000000000000000..620fbf63dc2aa913c05636a5536fc12d375fb409 --- /dev/null +++ b/0094-syscare-build-add-debug-option-to-kpatch-build.patch @@ -0,0 +1,43 @@ +From f6fed7d3a7163c79634c3e9c9921657a987176e8 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 15 May 2025 10:10:09 +0800 +Subject: [PATCH] syscare-build: add "--debug" option to kpatch-build + +Signed-off-by: renoseven +--- + syscare-build/src/patch/kernel_patch/kpatch_builder.rs | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/syscare-build/src/patch/kernel_patch/kpatch_builder.rs b/syscare-build/src/patch/kernel_patch/kpatch_builder.rs +index 07d4a85..202611d 100644 +--- a/syscare-build/src/patch/kernel_patch/kpatch_builder.rs ++++ b/syscare-build/src/patch/kernel_patch/kpatch_builder.rs +@@ -56,6 +56,7 @@ struct KBuildParameters { + patch_files: Vec, + jobs: usize, + skip_compiler_check: bool, ++ verbose: bool, + } + + struct KernelPatchEntity { +@@ -159,6 +160,7 @@ impl KernelPatchBuilder { + patch_files: build_params.patch_files.to_owned(), + jobs: build_params.jobs, + skip_compiler_check: build_params.skip_compiler_check, ++ verbose: build_params.verbose, + }) + } + +@@ -257,6 +259,9 @@ impl KernelPatchBuilder { + if kbuild_params.skip_compiler_check { + cmd_args.arg("--skip-compiler-check"); + } ++ if kbuild_params.verbose { ++ cmd_args.arg("--debug"); ++ } + cmd_args.arg("--skip-cleanup"); + + cmd_args +-- +2.43.0 + diff --git a/0095-Fix-invalid-url-for-syscare-build-readme.patch b/0095-Fix-invalid-url-for-syscare-build-readme.patch new file mode 100644 index 0000000000000000000000000000000000000000..5a0acbdd4cf5b2bb8c2538e45b05812bb4d63994 --- /dev/null +++ b/0095-Fix-invalid-url-for-syscare-build-readme.patch @@ -0,0 +1,43 @@ +From 9616a50288c23336dfcb41c75fadc2b31099960a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=E8=99=AB=E5=84=BF=E9=A3=9E?= +Date: Wed, 19 Mar 2025 01:59:06 +0000 +Subject: [PATCH] Fix invalid url for syscare-build readme +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: 虫儿飞 +--- + README.en.md | 2 +- + README.md | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/README.en.md b/README.en.md +index d004fa8..66734a5 100644 +--- a/README.en.md ++++ b/README.en.md +@@ -72,7 +72,7 @@ $ syscare build \ + --patch ./0001-test.patch + ``` + +-For detailed instructions on patch production, please see builder/README.md ++For detailed instructions on patch production, please see syscare-build/README.md + + ### Patch management + +diff --git a/README.md b/README.md +index 15d4d48..57f2a4e 100644 +--- a/README.md ++++ b/README.md +@@ -93,7 +93,7 @@ $ syscare build \ + --patch ./0001-test.patch + ``` + +-补丁制作详细使用说明请见[builder/README.md](https://gitee.com/openeuler/syscare/blob/master/builder/README.md) ++补丁制作详细使用说明请见[syscare-build/README.md](https://gitee.com/openeuler/syscare/blob/master/syscare-build/README.md) + + + +-- +2.43.0 + diff --git a/0096-doc-sync-master-document.patch b/0096-doc-sync-master-document.patch new file mode 100644 index 0000000000000000000000000000000000000000..1eef171cefa90b6b02e63ec5c8fbbed7550de8ca --- /dev/null +++ b/0096-doc-sync-master-document.patch @@ -0,0 +1,50 @@ +From e2d5945f7565cb22cd5464a7f4ac78ff90330067 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 15 May 2025 19:25:56 +0800 +Subject: [PATCH] doc: sync master document + +Signed-off-by: renoseven +--- + README.md | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/README.md b/README.md +index 57f2a4e..b740ace 100644 +--- a/README.md ++++ b/README.md +@@ -33,6 +33,8 @@ + + * 编译并安装 + ++ PS: 直接编译在应用补丁的时候会显示缺少依赖,建议通过rpm包安装 ++ + ```bash + git clone https://gitee.com/openeuler/syscare.git + cd syscare +@@ -41,6 +43,11 @@ + cmake -DCMAKE_INSTALL_PREFIX=/usr -DKERNEL_VERSION=$(uname -r) .. + make + make install ++ ++ mkdir -p /usr/lib/syscare/patches ++ systemctl daemon-reload ++ systemctl enable syscare ++ systemctl start syscare + ``` + + * 离线编译 +@@ -63,7 +70,11 @@ + ```bash + rpm -ivh syscare-*.rpm + ``` ++或者 + ++``` ++dnf install syscare-*.rpm ++``` + + + ## 使用说明 +-- +2.43.0 + diff --git a/0097-common-rewrite-fs-glob.patch b/0097-common-rewrite-fs-glob.patch new file mode 100644 index 0000000000000000000000000000000000000000..ffcba5a4f1aea474407744de84d5ae03778a4b24 --- /dev/null +++ b/0097-common-rewrite-fs-glob.patch @@ -0,0 +1,319 @@ +From 2197658b737e221043971909ec22559bea7332f6 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 18 Apr 2025 19:14:27 +0800 +Subject: [PATCH] common: rewrite fs::glob + +1. remove fs_impl::glob() +2. add fs::glob::{Glob, glob} + +Signed-off-by: renoseven +--- + syscare-common/src/fs/fs_impl.rs | 102 ------------------- + syscare-common/src/fs/glob.rs | 166 +++++++++++++++++++++++++++++++ + syscare-common/src/fs/mod.rs | 2 + + 3 files changed, 168 insertions(+), 102 deletions(-) + create mode 100644 syscare-common/src/fs/glob.rs + +diff --git a/syscare-common/src/fs/fs_impl.rs b/syscare-common/src/fs/fs_impl.rs +index 58f97c3..f5393f8 100644 +--- a/syscare-common/src/fs/fs_impl.rs ++++ b/syscare-common/src/fs/fs_impl.rs +@@ -565,108 +565,6 @@ pub fn copy_dir_contents, Q: AsRef>(src_dir: P, dst_dir: Q) + Ok(()) + } + +-pub fn glob>(path: P) -> io::Result> { +- const CURRENT_DIR: Component = Component::CurDir; +- const WILDCARD_ONE: char = '?'; +- const WILDCARD_ALL: char = '*'; +- const WILDCARD_RECURSIVE: &str = "**"; +- +- fn match_name(name: &OsStr, pattern: &OsStr) -> bool { +- let name: Vec<_> = name.chars().collect(); +- let pattern: Vec<_> = pattern.chars().collect(); +- +- let (mut name_idx, mut patt_idx, mut star_idx, mut match_idx) = (0, 0, None, 0); +- +- while name_idx < name.len() { +- if patt_idx < pattern.len() +- && (pattern[patt_idx] == WILDCARD_ONE || pattern[patt_idx] == name[name_idx]) +- { +- name_idx += 1; +- patt_idx += 1; +- } else if patt_idx < pattern.len() && pattern[patt_idx] == WILDCARD_ALL { +- star_idx = Some(patt_idx); +- match_idx = name_idx; +- patt_idx += 1; +- } else if let Some(star) = star_idx { +- patt_idx = star + 1; +- match_idx += 1; +- name_idx = match_idx; +- } else { +- return false; +- } +- } +- +- while patt_idx < pattern.len() && pattern[patt_idx] == WILDCARD_ALL { +- patt_idx += 1; +- } +- +- patt_idx == pattern.len() +- } +- +- let pattern = path.as_ref(); +- let base_dir = if pattern.is_relative() && !pattern.starts_with(CURRENT_DIR.as_os_str()) { +- PathBuf::from(CURRENT_DIR.as_os_str()) +- } else { +- PathBuf::new() +- }; +- let components = pattern.components().collect::>(); +- +- let mut result = Vec::new(); +- let mut stack = vec![(base_dir, 0)]; +- +- while let Some((mut curr_dir, mut comp_idx)) = stack.pop() { +- let comp_len = components.len(); +- while comp_idx < comp_len { +- if let Component::Normal(pattern) = components[comp_idx] { +- if pattern == WILDCARD_RECURSIVE { +- if let Ok(read_dir) = self::read_dir(&curr_dir) { +- stack.push((curr_dir.clone(), comp_idx + 1)); +- for dir_entry in read_dir.flatten() { +- let next_path = dir_entry.path(); +- if next_path.is_dir() { +- stack.push((next_path.clone(), comp_idx)); +- } +- if comp_idx + 1 == comp_len { +- result.push(next_path); +- continue; +- } +- stack.push((next_path, comp_idx + 1)); +- } +- } +- break; +- } else if pattern.contains(WILDCARD_ONE) || pattern.contains(WILDCARD_ALL) { +- if let Ok(read_dir) = self::read_dir(&curr_dir) { +- for dir_entry in read_dir.flatten() { +- let next_path = dir_entry.path(); +- let file_name = next_path.file_name().unwrap_or_default(); +- if !match_name(file_name, pattern) { +- continue; +- } +- if comp_idx + 1 == comp_len { +- result.push(next_path); +- continue; +- } +- if next_path.is_dir() { +- stack.push((next_path, comp_idx + 1)); +- } +- } +- } +- break; +- } +- } +- +- curr_dir.push(components[comp_idx]); +- if curr_dir.exists() && (comp_idx + 1 == comp_len) { +- result.push(curr_dir.clone()); +- break; +- } +- comp_idx += 1; +- } +- } +- +- Ok(result) +-} +- + pub fn sync() { + nix::unistd::sync() + } +diff --git a/syscare-common/src/fs/glob.rs b/syscare-common/src/fs/glob.rs +new file mode 100644 +index 0000000..9f4027f +--- /dev/null ++++ b/syscare-common/src/fs/glob.rs +@@ -0,0 +1,166 @@ ++use std::{ ++ ffi::{OsStr, OsString}, ++ fs, ++ io::Result, ++ path::{Path, PathBuf}, ++}; ++ ++use crate::{ffi::OsStrExt, os_str::CharByte}; ++ ++const WILDCARD_ONE: char = '?'; ++const WILDCARD_ALL: char = '*'; ++const WILDCARD_RECURSIVE: &str = "**"; ++ ++pub struct Glob { ++ components: Vec, ++ stack: Vec<(PathBuf, usize)>, // current path, component index ++} ++ ++impl Glob { ++ fn match_chars(name: I, mut pattern: P) -> bool ++ where ++ I: Iterator, ++ P: Iterator, ++ { ++ for current in name { ++ match pattern.next() { ++ Some(matching) => { ++ if matching == WILDCARD_ONE { ++ continue; // matched one char ++ } ++ if matching == WILDCARD_ALL { ++ return true; // matched all chars ++ } ++ if current != matching { ++ return false; // not matched ++ } ++ } ++ None => return false, // pattern not enough ++ } ++ } ++ ++ true ++ } ++ ++ fn match_component_name(name: &OsStr, component: &OsStr) -> bool { ++ if !Self::match_chars(name.chars(), component.chars()) { ++ return false; ++ } ++ // If pattern contains "*", we have to do reverse match to ++ // make sure tail chars were also matched to the pattern. ++ if component.contains(WILDCARD_ALL) { ++ return Self::match_chars(name.chars().rev(), component.chars().rev()); ++ } ++ ++ true ++ } ++ ++ fn match_component(&mut self, path: PathBuf, index: usize) -> Result> { ++ let last_index = self.components.len() - 1; ++ ++ for dir_entry in fs::read_dir(&path)? { ++ let next_path = dir_entry?.path(); ++ let next_name = next_path.file_name().unwrap_or_default(); ++ ++ let component = self.components[index].as_os_str(); ++ if !Self::match_component_name(next_name, component) { ++ continue; // not matched, skip ++ } ++ ++ if index == last_index { ++ return Ok(Some(next_path)); ++ } ++ ++ if next_path.is_dir() { ++ self.stack.push((next_path, index + 1)); ++ } ++ } ++ ++ Ok(None) ++ } ++ ++ fn match_recursive_wildcard(&mut self, path: PathBuf, index: usize) -> Result<()> { ++ // push files & directories in current directory to stack ++ for dir_entry in fs::read_dir(&path)? { ++ let next_path = dir_entry?.path(); ++ if next_path.is_dir() { ++ self.stack.push((next_path, index)); // recursive match, keep index ++ } ++ } ++ // push current path back to stack, match next component ++ self.stack.push((path, index + 1)); ++ ++ Ok(()) ++ } ++ ++ fn match_multiple_wildcard(&mut self, path: PathBuf, index: usize) -> Result<()> { ++ // push files & directories in current directory to stack ++ for dir_entry in fs::read_dir(&path)? { ++ let next_path = dir_entry?.path(); ++ if next_path.is_dir() { ++ self.stack.push((next_path, index + 1)); ++ } ++ } ++ // push current path back to stack, match next component ++ self.stack.push((path, index + 1)); ++ ++ Ok(()) ++ } ++} ++ ++impl Iterator for Glob { ++ type Item = Result; ++ ++ fn next(&mut self) -> Option { ++ while let Some((mut curr_path, mut index)) = self.stack.pop() { ++ let last_index = self.components.len() - 1; ++ ++ // iterate all of components over matching path ++ while index <= last_index { ++ let component = self.components[index].as_os_str(); ++ ++ if component == WILDCARD_RECURSIVE { ++ if let Err(e) = self.match_recursive_wildcard(curr_path, index) { ++ return Some(Err(e)); ++ } ++ } else if component == OsStr::new(&WILDCARD_ALL.to_string()) { ++ if let Err(e) = self.match_multiple_wildcard(curr_path, index) { ++ return Some(Err(e)); ++ } ++ } else if component.contains(WILDCARD_ONE) || component.contains(WILDCARD_ALL) { ++ let result = self.match_component(curr_path, index).transpose(); ++ if result.is_some() { ++ return result; ++ } ++ } else { ++ // normal component, push to current path ++ curr_path.push(component); ++ ++ if (index == last_index) && curr_path.exists() { ++ return Some(Ok(curr_path.clone())); ++ } ++ ++ index += 1; ++ continue; ++ } ++ ++ break; ++ } ++ } ++ ++ None ++ } ++} ++ ++pub fn glob>(path: P) -> Glob { ++ let match_dir = path.as_ref().to_path_buf(); ++ let matching = match_dir ++ .components() ++ .map(|c| c.as_os_str().to_os_string()) ++ .collect::>(); ++ ++ Glob { ++ components: matching, ++ stack: vec![(match_dir, 0)], ++ } ++} +diff --git a/syscare-common/src/fs/mod.rs b/syscare-common/src/fs/mod.rs +index 6091455..a5e43cd 100644 +--- a/syscare-common/src/fs/mod.rs ++++ b/syscare-common/src/fs/mod.rs +@@ -14,8 +14,10 @@ + + mod flock; + mod fs_impl; ++mod glob; + mod mapped_file; + + pub use flock::*; + pub use fs_impl::*; ++pub use glob::*; + pub use mapped_file::*; +-- +2.43.0 + diff --git a/0098-common-rewrite-fs-components.patch b/0098-common-rewrite-fs-components.patch new file mode 100644 index 0000000000000000000000000000000000000000..4ae5447f1dff00fb9f62b458e41927d3e97f14f3 --- /dev/null +++ b/0098-common-rewrite-fs-components.patch @@ -0,0 +1,488 @@ +From 774d52917b516c2b8b88d196d5b56d19bdfc5d39 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 21 Apr 2025 19:35:29 +0800 +Subject: [PATCH] common: rewrite fs components + +FileLock: +1. change fs::FileLock::new() from private fn +2. change fs::FileLock::new() retval + from anyhow::Result to std::io::Result +3. remove fs::FileLock member: path, kind +4. impl std::ops::{Deref, DerefMut} + for fs::FileLock +5. impl fs::flock() + +FileMmap: +1. rename fs::mapped_file -> fs::mmap +2. rename fs::MappedFile to fs::FileMmap +3. rename fs::FileMmap::open() to FileMmap::new() +4. change fs::FileMmap::new() to private fn +5. change fs::FileMmap::new() retval + from anyhow::Result to std::io::Result +6. remove fs::FileMmap::as_bytes() +7. impl std::ops::Deref for fs::FileMmap +8. impl fs::mmap() + +Glob: +1. impl fs::Glob::new() + +Signed-off-by: renoseven +--- + syscare-common/src/fs/flock.rs | 133 +++++++++++++-------------- + syscare-common/src/fs/glob.rs | 24 +++-- + syscare-common/src/fs/mapped_file.rs | 109 ---------------------- + syscare-common/src/fs/mmap.rs | 77 ++++++++++++++++ + syscare-common/src/fs/mod.rs | 4 +- + 5 files changed, 156 insertions(+), 191 deletions(-) + delete mode 100644 syscare-common/src/fs/mapped_file.rs + create mode 100644 syscare-common/src/fs/mmap.rs + +diff --git a/syscare-common/src/fs/flock.rs b/syscare-common/src/fs/flock.rs +index 29bff55..a1ca6ca 100644 +--- a/syscare-common/src/fs/flock.rs ++++ b/syscare-common/src/fs/flock.rs +@@ -14,11 +14,12 @@ + + use std::{ + fs::File, +- os::unix::io::{AsRawFd, RawFd}, +- path::{Path, PathBuf}, ++ io::Result, ++ ops::{Deref, DerefMut}, ++ os::unix::io::AsRawFd, ++ path::Path, + }; + +-use anyhow::{anyhow, Context, Result}; + use nix::fcntl; + + #[derive(Debug)] +@@ -31,112 +32,104 @@ pub enum FileLockType { + + #[derive(Debug)] + pub struct FileLock { +- path: PathBuf, + file: File, +- kind: FileLockType, + } + + impl FileLock { +- pub fn new>(path: P, kind: FileLockType) -> Result { +- let file_path = path.as_ref(); +- +- let file = if file_path.is_file() { +- File::open(file_path) +- .map_err(|e| anyhow!("Failed to open lock file {}, {}", file_path.display(), e))? +- } else { +- File::create(file_path) +- .map_err(|e| anyhow!("Failed to create lock file {}, {}", file_path.display(), e))? +- }; +- ++ fn new>(file_path: P, kind: FileLockType) -> Result { ++ let file_path = file_path.as_ref(); + let flock = Self { +- path: file_path.to_path_buf(), +- file, +- kind, ++ file: if file_path.exists() { ++ File::open(file_path)? ++ } else { ++ File::create(file_path)? ++ }, + }; +- flock.acquire_lock()?; ++ flock.acquire(kind)?; + + Ok(flock) + } +-} + +-impl FileLock { + #[inline] +- fn acquire_lock(&self) -> Result<()> { ++ fn acquire(&self, kind: FileLockType) -> Result<()> { + let fd = self.file.as_raw_fd(); +- let arg = match self.kind { ++ let arg = match kind { + FileLockType::Shared => fcntl::FlockArg::LockShared, + FileLockType::Exclusive => fcntl::FlockArg::LockExclusive, + FileLockType::SharedNonBlock => fcntl::FlockArg::LockSharedNonblock, + FileLockType::ExclusiveNonBlock => fcntl::FlockArg::LockExclusiveNonblock, + }; +- fcntl::flock(fd, arg) +- .with_context(|| format!("Failed to acquire flock on {}", self.path.display())) ++ fcntl::flock(fd, arg)?; ++ ++ Ok(()) + } + + #[inline] +- fn release_lock(&self) -> Result<()> { ++ fn release(&self) { + let fd = self.file.as_raw_fd(); + let arg = fcntl::FlockArg::Unlock; +- fcntl::flock(fd, arg) +- .with_context(|| format!("Failed to release flock on {}", self.path.display())) ++ fcntl::flock(fd, arg).expect("Failed to release file lock"); + } + } + +-impl AsRawFd for FileLock { +- fn as_raw_fd(&self) -> RawFd { +- self.file.as_raw_fd() ++impl Deref for FileLock { ++ type Target = File; ++ ++ fn deref(&self) -> &Self::Target { ++ &self.file ++ } ++} ++ ++impl DerefMut for FileLock { ++ fn deref_mut(&mut self) -> &mut Self::Target { ++ &mut self.file + } + } + + impl Drop for FileLock { + fn drop(&mut self) { +- self.release_lock().ok(); ++ self.release(); + } + } + +-#[test] +-fn test() { +- use std::fs; +- +- const EXIST_FILE: &str = "/etc/os-release"; +- const NON_EXIST_FILE: &str = "/tmp/flock_test"; ++pub fn flock>(file_path: P, kind: FileLockType) -> Result { ++ FileLock::new(file_path, kind) ++} + +- println!("Testing exclusive flock on {}...", NON_EXIST_FILE); +- fs::remove_file(NON_EXIST_FILE).ok(); ++#[test] ++fn test() -> anyhow::Result<()> { ++ use anyhow::{ensure, Context}; + +- let exclusive_lock = FileLock::new(NON_EXIST_FILE, FileLockType::ExclusiveNonBlock) +- .expect("Failed to create exclusive flock"); +- drop(exclusive_lock); ++ use std::fs; + +- println!("Testing shared flock on {}...", NON_EXIST_FILE); +- fs::remove_file(NON_EXIST_FILE).ok(); +- let shared_lock = FileLock::new(NON_EXIST_FILE, FileLockType::SharedNonBlock) +- .expect("Failed to create shared flock"); ++ let file_path = std::env::temp_dir().join("flock_test"); ++ fs::remove_file(&file_path)?; ++ ++ println!("Testing shared flock on {}...", file_path.display()); ++ let shared_lock = self::flock(&file_path, FileLockType::SharedNonBlock) ++ .context("Failed to create shared flock")?; ++ let shared_lock1 = self::flock(&file_path, FileLockType::SharedNonBlock) ++ .context("Failed to create shared flock")?; ++ ensure!( ++ self::flock(&file_path, FileLockType::ExclusiveNonBlock).is_err(), ++ "Exclusive flock should be failed" ++ ); + drop(shared_lock); ++ drop(shared_lock1); + +- fs::remove_file(NON_EXIST_FILE).ok(); +- +- println!("Testing exclusive flock on {}...", EXIST_FILE); +- let exclusive_lock = FileLock::new(EXIST_FILE, FileLockType::ExclusiveNonBlock) +- .expect("Failed to create exclusive flock"); +- let _exclusive_err = FileLock::new(EXIST_FILE, FileLockType::ExclusiveNonBlock) +- .expect_err("Exclusive flock should be failed"); +- let _shared_err = FileLock::new(EXIST_FILE, FileLockType::SharedNonBlock) +- .expect_err("Shared flock should be failed"); ++ println!("Testing exclusive flock on {}...", file_path.display()); ++ let exclusive_lock = self::flock(&file_path, FileLockType::ExclusiveNonBlock) ++ .context("Failed to create exclusive flock")?; ++ ensure!( ++ self::flock(&file_path, FileLockType::SharedNonBlock).is_err(), ++ "Shared flock should be failed" ++ ); ++ ensure!( ++ self::flock(&file_path, FileLockType::ExclusiveNonBlock).is_err(), ++ "Exclusive flock should be failed" ++ ); + + drop(exclusive_lock); + +- println!("Testing shared flock on {}...", EXIST_FILE); +- let shared_lock1 = FileLock::new(EXIST_FILE, FileLockType::SharedNonBlock) +- .expect("Failed to create shared flock"); +- let shared_lock2 = FileLock::new(EXIST_FILE, FileLockType::SharedNonBlock) +- .expect("Failed to create shared flock"); +- let _exclusive_err = FileLock::new(EXIST_FILE, FileLockType::ExclusiveNonBlock) +- .expect_err("Exclusive flock should be failed"); +- let shared_lock3 = FileLock::new(EXIST_FILE, FileLockType::SharedNonBlock) +- .expect("Failed to create shared flock"); +- +- drop(shared_lock1); +- drop(shared_lock2); +- drop(shared_lock3); ++ Ok(()) + } +diff --git a/syscare-common/src/fs/glob.rs b/syscare-common/src/fs/glob.rs +index 9f4027f..8165343 100644 +--- a/syscare-common/src/fs/glob.rs ++++ b/syscare-common/src/fs/glob.rs +@@ -17,6 +17,19 @@ pub struct Glob { + } + + impl Glob { ++ fn new>(path: P) -> Self { ++ let match_dir = path.as_ref().to_path_buf(); ++ let matching = match_dir ++ .components() ++ .map(|c| c.as_os_str().to_os_string()) ++ .collect::>(); ++ ++ Glob { ++ components: matching, ++ stack: vec![(match_dir, 0)], ++ } ++ } ++ + fn match_chars(name: I, mut pattern: P) -> bool + where + I: Iterator, +@@ -153,14 +166,5 @@ impl Iterator for Glob { + } + + pub fn glob>(path: P) -> Glob { +- let match_dir = path.as_ref().to_path_buf(); +- let matching = match_dir +- .components() +- .map(|c| c.as_os_str().to_os_string()) +- .collect::>(); +- +- Glob { +- components: matching, +- stack: vec![(match_dir, 0)], +- } ++ Glob::new(path) + } +diff --git a/syscare-common/src/fs/mapped_file.rs b/syscare-common/src/fs/mapped_file.rs +deleted file mode 100644 +index d05e307..0000000 +--- a/syscare-common/src/fs/mapped_file.rs ++++ /dev/null +@@ -1,109 +0,0 @@ +-// SPDX-License-Identifier: Mulan PSL v2 +-/* +- * Copyright (c) 2024 Huawei Technologies Co., Ltd. +- * syscare-common is licensed under Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. +- * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +- * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +- * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +- * See the Mulan PSL v2 for more details. +- */ +- +-use std::{ +- io::{BufRead, Cursor, Read}, +- os::unix::io::AsRawFd, +- path::Path, +-}; +- +-use anyhow::{ensure, Context, Result}; +-use memmap2::{Mmap, MmapOptions}; +- +-use super::flock::{FileLock, FileLockType}; +- +-#[derive(Debug)] +-pub struct MappedFile { +- _flock: FileLock, +- cursor: Cursor, +-} +- +-impl MappedFile { +- pub fn open>(path: P) -> Result { +- let file_path = path.as_ref(); +- ensure!( +- !file_path.starts_with("/proc"), +- "Mmap does not support procfs" +- ); +- +- let flock = FileLock::new(file_path, FileLockType::Shared)?; +- /* +- * SAFETY: +- * All file-backed memory map constructors are marked unsafe because of the +- * potential for Undefined Behavior (UB) using the map if the underlying file +- * is subsequently modified, in or out of process. +- * Our implementation uses shared file lock to avoid cross-process file access. +- * This mapped area would be safe. +- */ +- let mmap = unsafe { +- MmapOptions::new() +- .map(flock.as_raw_fd()) +- .with_context(|| format!("Failed to mmap file {}", path.as_ref().display()))? +- }; +- +- let cursor = Cursor::new(mmap); +- Ok(Self { +- _flock: flock, +- cursor, +- }) +- } +- +- pub fn as_bytes(&self) -> &[u8] { +- self.cursor.get_ref() +- } +-} +- +-impl Read for MappedFile { +- fn read(&mut self, buf: &mut [u8]) -> std::io::Result { +- self.cursor.read(buf) +- } +-} +- +-impl BufRead for MappedFile { +- fn fill_buf(&mut self) -> std::io::Result<&[u8]> { +- self.cursor.fill_buf() +- } +- +- fn consume(&mut self, amt: usize) { +- self.cursor.consume(amt) +- } +-} +- +-#[test] +-fn test() { +- use std::{fs::File, io::Read}; +- +- const PROC_FS_PATH: &str = "/proc/version"; +- const FILE_PATH: &str = "/etc/os-release"; +- +- println!("Testing MappedFile..."); +- let mut file_buf = vec![]; +- let mut mapped_buf = vec![]; +- +- let mut normal_file = File::open(FILE_PATH).expect("Failed to open normal file"); +- normal_file +- .read_to_end(&mut file_buf) +- .expect("Failed to read normal file"); +- +- let mut mapped_file = MappedFile::open(FILE_PATH).expect("Failed to open mapped file"); +- mapped_file +- .read_to_end(&mut mapped_buf) +- .expect("Failed to read mapped file"); +- +- let _map_procfs_err = +- MappedFile::open(PROC_FS_PATH).expect_err("Procfs should not be supported"); +- +- assert_eq!(file_buf, mapped_buf); +- assert_eq!(mapped_buf, mapped_file.as_bytes()); +-} +diff --git a/syscare-common/src/fs/mmap.rs b/syscare-common/src/fs/mmap.rs +new file mode 100644 +index 0000000..b65f170 +--- /dev/null ++++ b/syscare-common/src/fs/mmap.rs +@@ -0,0 +1,77 @@ ++// SPDX-License-Identifier: Mulan PSL v2 ++/* ++ * Copyright (c) 2024 Huawei Technologies Co., Ltd. ++ * syscare-common is licensed under Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, ++ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, ++ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++use std::{io::Result, ops::Deref, os::fd::AsRawFd, path::Path}; ++ ++use memmap2::{Advice, Mmap, MmapOptions}; ++ ++use super::flock::*; ++ ++#[derive(Debug)] ++pub struct FileMmap { ++ _lock: FileLock, ++ mmap: Mmap, ++} ++ ++impl FileMmap { ++ fn new>(file_path: P) -> Result { ++ /* ++ * SAFETY: ++ * All file-backed memory map constructors are marked unsafe because of the ++ * potential for Undefined Behavior (UB) using the map if the underlying file ++ * is subsequently modified, in or out of process. ++ * Our implementation uses shared file lock to avoid cross-process file access. ++ * This mapped area would be safe. ++ */ ++ let lock = flock(file_path, FileLockType::Shared)?; ++ let mmap = unsafe { MmapOptions::new().map(lock.as_raw_fd())? }; ++ mmap.advise(Advice::Random)?; ++ ++ Ok(Self { _lock: lock, mmap }) ++ } ++} ++ ++impl Deref for FileMmap { ++ type Target = [u8]; ++ ++ fn deref(&self) -> &Self::Target { ++ &self.mmap ++ } ++} ++ ++pub fn mmap>(file_path: P) -> std::io::Result { ++ FileMmap::new(file_path) ++} ++ ++#[test] ++fn test() -> anyhow::Result<()> { ++ use anyhow::Context; ++ ++ const FILE_PATH: &str = "/etc/os-release"; ++ const SYS_FS_PATH: &str = "/sys/kernel/vmcoreinfo"; ++ const PROC_FS_PATH: &str = "/proc/version"; ++ ++ println!("Testing FileMmap..."); ++ let orig_file = ++ std::fs::read(FILE_PATH).with_context(|| format!("Failed to open file {}", FILE_PATH))?; ++ let map_file = ++ self::mmap(FILE_PATH).with_context(|| format!("Failed to mmap file {}", FILE_PATH))?; ++ ++ let _ = self::mmap(SYS_FS_PATH).expect_err("Sysfs cannot not be mapped"); ++ let _ = self::mmap(PROC_FS_PATH).expect_err("Procfs cannot not be mapped"); ++ ++ assert_eq!(orig_file, map_file.as_ref()); ++ ++ Ok(()) ++} +diff --git a/syscare-common/src/fs/mod.rs b/syscare-common/src/fs/mod.rs +index a5e43cd..3526915 100644 +--- a/syscare-common/src/fs/mod.rs ++++ b/syscare-common/src/fs/mod.rs +@@ -15,9 +15,9 @@ + mod flock; + mod fs_impl; + mod glob; +-mod mapped_file; ++mod mmap; + + pub use flock::*; + pub use fs_impl::*; + pub use glob::*; +-pub use mapped_file::*; ++pub use mmap::*; +-- +2.43.0 + diff --git a/0099-syscare-adapt-common-fs-changes.patch b/0099-syscare-adapt-common-fs-changes.patch new file mode 100644 index 0000000000000000000000000000000000000000..9dedc6e38aa371edb7c07ffd2b710ee7fc80387d --- /dev/null +++ b/0099-syscare-adapt-common-fs-changes.patch @@ -0,0 +1,45 @@ +From 3a38a683eb0137e3348a35ab35bac5459bcd75d4 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 21 Apr 2025 20:00:59 +0800 +Subject: [PATCH] syscare: adapt common::fs changes + +Signed-off-by: renoseven +--- + syscare/src/rpc/client.rs | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/syscare/src/rpc/client.rs b/syscare/src/rpc/client.rs +index 3428984..e24227a 100644 +--- a/syscare/src/rpc/client.rs ++++ b/syscare/src/rpc/client.rs +@@ -17,7 +17,7 @@ use std::{ + path::{Path, PathBuf}, + }; + +-use anyhow::{anyhow, ensure, Error, Result}; ++use anyhow::{anyhow, ensure, Context, Error, Result}; + use jsonrpc::{ + serde_json::value::RawValue, + simple_uds::{self, UdsTransport}, +@@ -26,7 +26,7 @@ use jsonrpc::{ + use log::debug; + use serde::{Deserialize, Serialize}; + +-use syscare_common::fs::{FileLock, FileLockType}; ++use syscare_common::fs::{self, FileLock}; + + #[derive(Debug, Default)] + pub struct RpcArguments { +@@ -80,7 +80,8 @@ impl RpcClient { + } + + pub fn lock(&self) -> Result { +- FileLock::new(&self.lock, FileLockType::Exclusive) ++ fs::flock(&self.lock, fs::FileLockType::Exclusive) ++ .with_context(|| format!("Failed to lock {}", self.lock.display())) + } + + pub fn call(&self, cmd: &str) -> Result +-- +2.43.0 + diff --git a/0100-syscared-adapt-common-fs-changes.patch b/0100-syscared-adapt-common-fs-changes.patch new file mode 100644 index 0000000000000000000000000000000000000000..4ff8918b9518707c10240076b29d13c9048f28de --- /dev/null +++ b/0100-syscared-adapt-common-fs-changes.patch @@ -0,0 +1,48 @@ +From c0b9d8e0d415758a72743500c7d90af00e719730 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 21 Apr 2025 20:02:16 +0800 +Subject: [PATCH] syscared: adapt common::fs changes + +Signed-off-by: renoseven +--- + syscared/src/patch/resolver/kpatch.rs | 6 +++--- + syscared/src/patch/resolver/upatch.rs | 6 +++--- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/syscared/src/patch/resolver/kpatch.rs b/syscared/src/patch/resolver/kpatch.rs +index 4ec35f4..f8885ff 100644 +--- a/syscared/src/patch/resolver/kpatch.rs ++++ b/syscared/src/patch/resolver/kpatch.rs +@@ -112,9 +112,9 @@ pub struct KpatchResolverImpl; + impl KpatchResolverImpl { + #[inline] + fn resolve_patch_file(patch: &mut KernelPatch) -> Result<()> { +- let patch_file = +- fs::MappedFile::open(&patch.patch_file).context("Failed to map patch file")?; +- let patch_elf = NativeFile::parse(patch_file.as_bytes()).context("Invalid patch format")?; ++ let patch_file = fs::mmap(&patch.patch_file) ++ .with_context(|| format!("Failed to mmap file {}", patch.patch_file.display()))?; ++ let patch_elf = NativeFile::parse(patch_file.as_ref()).context("Invalid patch format")?; + + // Read sections + let function_section = patch_elf +diff --git a/syscared/src/patch/resolver/upatch.rs b/syscared/src/patch/resolver/upatch.rs +index e49dff9..a5e4ad0 100644 +--- a/syscared/src/patch/resolver/upatch.rs ++++ b/syscared/src/patch/resolver/upatch.rs +@@ -93,9 +93,9 @@ pub struct UpatchResolverImpl; + impl UpatchResolverImpl { + #[inline] + fn resolve_patch_elf(patch: &mut UserPatch) -> Result<()> { +- let patch_file = +- fs::MappedFile::open(&patch.patch_file).context("Failed to map patch file")?; +- let patch_elf = NativeFile::parse(patch_file.as_bytes()).context("Invalid patch format")?; ++ let patch_file = fs::mmap(&patch.patch_file) ++ .with_context(|| format!("Failed to mmap file {}", patch.patch_file.display()))?; ++ let patch_elf = NativeFile::parse(patch_file.as_ref()).context("Invalid patch format")?; + + // Read sections + let function_section = patch_elf +-- +2.43.0 + diff --git a/0101-upatch-helper-optimize-compiler-flags.patch b/0101-upatch-helper-optimize-compiler-flags.patch new file mode 100644 index 0000000000000000000000000000000000000000..5e0c4304aa5b7744d1283b51211e05c6b28baa04 --- /dev/null +++ b/0101-upatch-helper-optimize-compiler-flags.patch @@ -0,0 +1,49 @@ +From 48918131470019e3918b27921c0b1bf388c29c23 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 23 Apr 2025 12:01:28 +0800 +Subject: [PATCH] upatch-helper: optimize compiler flags + +Signed-off-by: renoseven +--- + upatch-helper/src/main.rs | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/upatch-helper/src/main.rs b/upatch-helper/src/main.rs +index 303088c..782776f 100644 +--- a/upatch-helper/src/main.rs ++++ b/upatch-helper/src/main.rs +@@ -19,14 +19,17 @@ use uuid::Uuid; + + const UPATCH_CC_ENV: &str = "UPATCH_HELPER_CC"; + const UPATCH_CXX_ENV: &str = "UPATCH_HELPER_CXX"; ++const UPATCH_ID_PREFIX: &str = ".upatch_"; + + const OUTPUT_FLAG: &str = "-o"; +-const APPEND_ARGS: [&str; 3] = [ +- "-gdwarf", /* obtain debug information */ +- "-ffunction-sections", +- "-fdata-sections", ++ ++const APPEND_FLAGS: &[&str] = &[ ++ "-gdwarf", // generate dwarf debuginfo ++ "-ffunction-sections", // generate corresponding section for each function ++ "-fdata-sections", // generate corresponding section for each data ++ "-fmerge-constants", // merge constants with same value into one ++ "-fno-common", // avoid generating common block for uninitialized global variables + ]; +-const UPATCH_ID_PREFIX: &str = ".upatch_"; + + fn main() -> anyhow::Result<()> { + let exec_args = std::env::args_os().collect::>(); +@@ -48,7 +51,7 @@ fn main() -> anyhow::Result<()> { + + command.args(exec_args.iter().skip(1)); + if exec_args.iter().any(|arg| arg == OUTPUT_FLAG) { +- command.args(APPEND_ARGS); ++ command.args(APPEND_FLAGS); + command.arg(format!( + "-Wa,--defsym,{}{}=0", + UPATCH_ID_PREFIX, +-- +2.43.0 + diff --git a/0102-upatch-helper-support-clang-compiler.patch b/0102-upatch-helper-support-clang-compiler.patch new file mode 100644 index 0000000000000000000000000000000000000000..9fe9225aed4cd0e7b6e1c9c6b9350ddffdbc2112 --- /dev/null +++ b/0102-upatch-helper-support-clang-compiler.patch @@ -0,0 +1,163 @@ +From d8fa52663748d66d2e798b6c025eb3d8b115f3ca Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 23 Apr 2025 15:05:17 +0800 +Subject: [PATCH] upatch-helper: support clang compiler + +Signed-off-by: renoseven +--- + upatch-helper/src/main.rs | 124 +++++++++++++++++++++++++++----------- + 1 file changed, 88 insertions(+), 36 deletions(-) + +diff --git a/upatch-helper/src/main.rs b/upatch-helper/src/main.rs +index 782776f..cd83bc6 100644 +--- a/upatch-helper/src/main.rs ++++ b/upatch-helper/src/main.rs +@@ -12,57 +12,109 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{os::unix::process::CommandExt, path::Path, process::Command}; ++use std::{ ++ ffi::{OsStr, OsString}, ++ os::unix::{ffi::OsStrExt, process::CommandExt}, ++ path::{Path, PathBuf}, ++ process::Command, ++}; + +-use anyhow::{bail, Context}; ++use anyhow::{bail, Context, Result}; + use uuid::Uuid; + +-const UPATCH_CC_ENV: &str = "UPATCH_HELPER_CC"; +-const UPATCH_CXX_ENV: &str = "UPATCH_HELPER_CXX"; +-const UPATCH_ID_PREFIX: &str = ".upatch_"; ++const COMPILER_KEYWORDS_CC: &[&str] = &["cc", "clang"]; ++const COMPILER_KEYWORDS_CXX: &[&str] = &["++", "xx"]; + +-const OUTPUT_FLAG: &str = "-o"; ++const HELPER_ENV_NAME_CC: &str = "UPATCH_HELPER_CC"; ++const HELPER_ENV_NAME_CXX: &str = "UPATCH_HELPER_CXX"; ++const HELPER_ENV_NAMES: &[(&[&str], &str)] = &[ ++ (COMPILER_KEYWORDS_CC, HELPER_ENV_NAME_CC), ++ (COMPILER_KEYWORDS_CXX, HELPER_ENV_NAME_CXX), ++]; + +-const APPEND_FLAGS: &[&str] = &[ +- "-gdwarf", // generate dwarf debuginfo +- "-ffunction-sections", // generate corresponding section for each function +- "-fdata-sections", // generate corresponding section for each data +- "-fmerge-constants", // merge constants with same value into one +- "-fno-common", // avoid generating common block for uninitialized global variables ++const COMPILE_FLAG_NAME: &str = "-c"; ++const COMPILE_OPTIONS_GNU: &[&str] = &[ ++ "-gdwarf", // generate dwarf debuginfo ++ "-ffunction-sections", // generate corresponding section for each function ++ "-fdata-sections", // generate corresponding section for each data ++ "-fmerge-constants", // merge constants with same value into one ++ "-fno-common", // avoid generating common block for uninitialized global variables ++ "-fno-tree-slp-vectorize", // avoid converting scalar operations into SIMD instructions + ]; ++const COMPILE_OPTIONS_CLANG: &[&str] = &[ ++ "-gdwarf", ++ "-ffunction-sections", ++ "-fdata-sections", ++ "-fno-common", ++ "-fno-slp-vectorize", // avoid converting scalar operations into SIMD instructions ++ "-fno-integrated-as", // avoid using built-in llvm-as, which doesn't support "--defsym" ++]; ++ ++const UPATCH_ID_PREFIX: &str = ".upatch_"; ++ ++#[inline(always)] ++fn is_compilation(args: &[OsString]) -> bool { ++ args.iter().any(|arg| arg == COMPILE_FLAG_NAME) ++} ++ ++#[inline(always)] ++fn find_compiler(arg0: &OsStr) -> Result { ++ let file_name = Path::new(arg0).file_name().unwrap_or_default(); + +-fn main() -> anyhow::Result<()> { +- let exec_args = std::env::args_os().collect::>(); +- let exec_name = Path::new(&exec_args[0]) ++ // match compiler by file name ++ let env_entry = HELPER_ENV_NAMES.iter().find(|(keys, _)| { ++ keys.iter().any(|str| { ++ let key_bytes = str.as_bytes(); ++ file_name ++ .as_bytes() ++ .windows(key_bytes.len()) ++ .any(|window| window == key_bytes) ++ }) ++ }); ++ if let Some((_, env_name)) = env_entry { ++ return std::env::var_os(env_name) ++ .map(PathBuf::from) ++ .with_context(|| format!("Environment variable '{}' was not set", env_name)); ++ } ++ ++ bail!("No compiler found"); ++} ++ ++#[inline(always)] ++fn add_compile_options(command: &mut Command) { ++ let prog_name = Path::new(command.get_program()) + .file_name() +- .context("Cannot parse exec name")? +- .to_string_lossy(); +- let exec_path = if exec_name.contains("cc") { +- std::env::var_os(UPATCH_CC_ENV) +- .with_context(|| format!("Environment variable '{}' is not set", UPATCH_CC_ENV))? +- } else if exec_name.contains("++") { +- std::env::var_os(UPATCH_CXX_ENV) +- .with_context(|| format!("Environment variable '{}' is not set", UPATCH_CXX_ENV))? +- } else { +- bail!("Invalid exec name '{}'", exec_name); ++ .unwrap_or_default(); ++ let clang_name_bytes = COMPILER_KEYWORDS_CC[1].as_bytes(); ++ let is_clang = prog_name ++ .as_bytes() ++ .windows(clang_name_bytes.len()) ++ .any(|window| window == clang_name_bytes); ++ ++ let compiler_args = match is_clang { ++ true => COMPILE_OPTIONS_CLANG, ++ false => COMPILE_OPTIONS_GNU, + }; ++ let assembler_arg = format!("-Wa,--defsym,{}{}=0", UPATCH_ID_PREFIX, Uuid::new_v4()); ++ ++ command.args(compiler_args); ++ command.arg(assembler_arg); ++} + +- let mut command = Command::new(&exec_path); ++fn main() -> Result<()> { ++ let args: Vec<_> = std::env::args_os().collect(); ++ let compiler = self::find_compiler(&args[0])?; + +- command.args(exec_args.iter().skip(1)); +- if exec_args.iter().any(|arg| arg == OUTPUT_FLAG) { +- command.args(APPEND_FLAGS); +- command.arg(format!( +- "-Wa,--defsym,{}{}=0", +- UPATCH_ID_PREFIX, +- Uuid::new_v4(), +- )); ++ let mut command = Command::new(&compiler); ++ command.args(&args[1..]); ++ if self::is_compilation(&args) { ++ self::add_compile_options(&mut command); + } + + let err = command.exec(); + bail!( +- "Exec '{}' failed, {}", +- exec_path.to_string_lossy(), ++ "Failed to execute '{}', {}", ++ compiler.display(), + err.to_string().to_lowercase() + ); + } +-- +2.43.0 + diff --git a/0103-upatch-helper-support-cross-compilation.patch b/0103-upatch-helper-support-cross-compilation.patch new file mode 100644 index 0000000000000000000000000000000000000000..2dff7b0aad97b0386355aabfd5f51fcfb8a541f0 --- /dev/null +++ b/0103-upatch-helper-support-cross-compilation.patch @@ -0,0 +1,40 @@ +From 506f4ce996902f110f0b82e5a77e77251b5920fd Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 23 Apr 2025 18:09:04 +0800 +Subject: [PATCH] upatch-helper: support cross compilation + +Signed-off-by: renoseven +--- + upatch-helper/src/main.rs | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/upatch-helper/src/main.rs b/upatch-helper/src/main.rs +index cd83bc6..9676bef 100644 +--- a/upatch-helper/src/main.rs ++++ b/upatch-helper/src/main.rs +@@ -77,6 +77,22 @@ fn find_compiler(arg0: &OsStr) -> Result { + .with_context(|| format!("Environment variable '{}' was not set", env_name)); + } + ++ // exec name matched, read environment variable directly ++ let exec_path = std::env::current_exe()?; ++ let exec_name = exec_path.file_name().unwrap_or_default(); ++ if exec_name == file_name { ++ return HELPER_ENV_NAMES ++ .iter() ++ .rev() ++ .find_map(|&(_, env_name)| std::env::var_os(env_name).map(PathBuf::from)) ++ .with_context(|| { ++ format!( ++ "Environment variables '{}' and '{}' were not set", ++ HELPER_ENV_NAME_CC, HELPER_ENV_NAME_CXX ++ ) ++ }); ++ } ++ + bail!("No compiler found"); + } + +-- +2.43.0 + diff --git a/0104-upatch-helper-add-Werror-uninitialized-for-clang.patch b/0104-upatch-helper-add-Werror-uninitialized-for-clang.patch new file mode 100644 index 0000000000000000000000000000000000000000..688fbb7e174a7d266c8f47d36990221a1568a191 --- /dev/null +++ b/0104-upatch-helper-add-Werror-uninitialized-for-clang.patch @@ -0,0 +1,25 @@ +From 82b76a766f3cbab144c8bc8e7ab61e67b92ada06 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 8 May 2025 11:38:33 +0800 +Subject: [PATCH] upatch-helper: add --Werror=uninitialized for clang + +Signed-off-by: renoseven +--- + upatch-helper/src/main.rs | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/upatch-helper/src/main.rs b/upatch-helper/src/main.rs +index 9676bef..3992367 100644 +--- a/upatch-helper/src/main.rs ++++ b/upatch-helper/src/main.rs +@@ -48,6 +48,7 @@ const COMPILE_OPTIONS_CLANG: &[&str] = &[ + "-fno-common", + "-fno-slp-vectorize", // avoid converting scalar operations into SIMD instructions + "-fno-integrated-as", // avoid using built-in llvm-as, which doesn't support "--defsym" ++ "-Werror=uninitialized", // uninitialized variable may generate unexpected code under O2 optimization + ]; + + const UPATCH_ID_PREFIX: &str = ".upatch_"; +-- +2.43.0 + diff --git a/0105-upatch-build-execute-clean-before-first-time-buildin.patch b/0105-upatch-build-execute-clean-before-first-time-buildin.patch new file mode 100644 index 0000000000000000000000000000000000000000..a1e6ca11417d7f89aed0444ee698e6087dd13533 --- /dev/null +++ b/0105-upatch-build-execute-clean-before-first-time-buildin.patch @@ -0,0 +1,122 @@ +From 293508085f6cd28faed6d1181652b385ac49c48c Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 3 Apr 2025 16:20:20 +0800 +Subject: [PATCH] upatch-build: execute clean before first-time building + +1. set '--clean-cmd' default value to empty +2. execute clean command before first building +3. check '--prepare-cmd' existence before executing prepare command +4. check '--clean-cmd' existence before executing clean command + +Signed-off-by: renoseven +--- + upatch-build/src/args.rs | 13 +++++-------- + upatch-build/src/main.rs | 34 ++++++++++++++++++++++++++-------- + 2 files changed, 31 insertions(+), 16 deletions(-) + +diff --git a/upatch-build/src/args.rs b/upatch-build/src/args.rs +index 5871f82..f840095 100644 +--- a/upatch-build/src/args.rs ++++ b/upatch-build/src/args.rs +@@ -23,8 +23,8 @@ use which::which; + use super::{CLI_ABOUT, CLI_NAME, CLI_VERSION}; + + const DEFAULT_EMPTY_VALUE: &str = ""; +-const DEFAULT_SOURCE_EXT: [&str; 8] = ["h", "hpp", "hxx", "c", "cpp", "cxx", "in", "inc"]; +-const DEFAULT_COMPILERS: [&str; 2] = ["gcc", "g++"]; ++const DEFAULT_SOURCE_EXTS: &[&str] = &["h", "hpp", "hxx", "c", "cpp", "cxx", "in", "inc"]; ++const DEFAULT_COMPILERS: &[&str] = &["gcc", "g++"]; + const DEFAULT_BUILD_ROOT: &str = "."; + const DEFAULT_OUTPUT_DIR: &str = "."; + +@@ -52,7 +52,7 @@ pub struct Arguments { + pub source_dir: PathBuf, + + /// Source file extension(s) +- #[clap(long, multiple = true, default_values = &DEFAULT_SOURCE_EXT)] ++ #[clap(long, multiple = true, default_values = &DEFAULT_SOURCE_EXTS)] + pub source_ext: Vec, + + /// Build compiler(s) +@@ -60,14 +60,14 @@ pub struct Arguments { + pub compiler: Vec, + + /// Build prepare command +- #[clap(long, default_value = DEFAULT_EMPTY_VALUE)] ++ #[clap(long, default_value = DEFAULT_EMPTY_VALUE, hide_default_value = true)] + pub prepare_cmd: OsString, + + /// Build command + #[clap(short('c'), long)] + pub build_cmd: OsString, + +- /// Build clean command [default: ] ++ /// Build clean command + #[clap(long, default_value = DEFAULT_EMPTY_VALUE, hide_default_value = true)] + pub clean_cmd: OsString, + +@@ -139,9 +139,6 @@ impl Arguments { + if self.binary_dir.as_os_str().is_empty() { + self.binary_dir = self.source_dir.clone(); + } +- if self.clean_cmd.is_empty() { +- self.clean_cmd = self.prepare_cmd.clone(); +- } + + self + } +diff --git a/upatch-build/src/main.rs b/upatch-build/src/main.rs +index 51956d8..73d286f 100644 +--- a/upatch-build/src/main.rs ++++ b/upatch-build/src/main.rs +@@ -276,10 +276,19 @@ impl UpatchBuild { + self.check_debuginfo().context("Debuginfo check failed")?; + } + +- info!("Preparing '{}'", project); +- project +- .prepare() +- .with_context(|| format!("Failed to prepare {}", project))?; ++ if !self.args.prepare_cmd.is_empty() { ++ info!("Preparing '{}'", project); ++ project ++ .prepare() ++ .with_context(|| format!("Failed to prepare {}", project))?; ++ } ++ ++ if !self.args.clean_cmd.is_empty() { ++ info!("Cleaning '{}'", project); ++ project ++ .clean() ++ .with_context(|| format!("Failed to clean {}", project))?; ++ } + + if !self.args.keep_line_macros { + info!("Overriding line macros"); +@@ -297,10 +306,19 @@ impl UpatchBuild { + self.file_relation + .collect_original_build(object_dir, original_dir)?; + +- info!("Cleaning '{}'", project); +- project +- .clean() +- .with_context(|| format!("Failed to clean {}", project))?; ++ if !self.args.prepare_cmd.is_empty() { ++ info!("Preparing '{}'", project); ++ project ++ .prepare() ++ .with_context(|| format!("Failed to prepare {}", project))?; ++ } ++ ++ if !self.args.clean_cmd.is_empty() { ++ info!("Cleaning '{}'", project); ++ project ++ .clean() ++ .with_context(|| format!("Failed to clean {}", project))?; ++ } + + info!("Patching '{}'", project); + project +-- +2.43.0 + diff --git a/0106-upatch-build-rewrite-compiler-detection.patch b/0106-upatch-build-rewrite-compiler-detection.patch new file mode 100644 index 0000000000000000000000000000000000000000..a8611fa936ccba4a476deefbb438be6503cc6439 --- /dev/null +++ b/0106-upatch-build-rewrite-compiler-detection.patch @@ -0,0 +1,1545 @@ +From 84b924bc883fa1f3590ef08689a297f9b5ad0d29 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 17 Apr 2025 09:49:22 +0800 +Subject: [PATCH] upatch-build: rewrite compiler detection + +Dwarf: +1. remove dwarf::{Dwarf, Relocation} +2. add dwarf::{Producer, ProducerType, ProducerParser, ProducerIterator} +3. rewrite pruducer name parsing logic +4. rewrite producer vesrion parsing logic +5. support llvm assembler & clang compiler + +Compiler: +1. rename compiler::CompilerInfo -> compiler::Compiler +2. detection only compiles one test object +3. support cross compiler +4. support llvm linker + +Builder: +1. rewrite compiler detection logic +2. rewrite compiler version check logic +3. rewrite patch linking logic + +Signed-off-by: renoseven +--- + upatch-build/Cargo.toml | 2 + + upatch-build/src/compiler.rs | 274 ++++++++++----------- + upatch-build/src/dwarf.rs | 379 +++++++++++++++++++++++++++++ + upatch-build/src/dwarf/mod.rs | 274 --------------------- + upatch-build/src/dwarf/relocate.rs | 146 ----------- + upatch-build/src/main.rs | 210 +++++++++------- + upatch-build/src/project.rs | 21 +- + 7 files changed, 651 insertions(+), 655 deletions(-) + create mode 100644 upatch-build/src/dwarf.rs + delete mode 100644 upatch-build/src/dwarf/mod.rs + delete mode 100644 upatch-build/src/dwarf/relocate.rs + +diff --git a/upatch-build/Cargo.toml b/upatch-build/Cargo.toml +index 88d88b3..5834d28 100644 +--- a/upatch-build/Cargo.toml ++++ b/upatch-build/Cargo.toml +@@ -21,6 +21,8 @@ log = { version = "0.4" } + memmap2 = { version = "0.9" } + memoffset = { version = "0.7" } + object = { version = "0.29", features = ["write"] } ++once_cell = { version = "1.18" } ++regex = { version = "1.7" } + serde = { version = "1.0", features = ["derive"] } + typed-arena = { version = "2.0" } + which = { version = "4.4" } +diff --git a/upatch-build/src/compiler.rs b/upatch-build/src/compiler.rs +index ed23bf4..0711033 100644 +--- a/upatch-build/src/compiler.rs ++++ b/upatch-build/src/compiler.rs +@@ -13,183 +13,171 @@ + */ + + use std::{ +- ffi::OsString, ++ ffi::{OsStr, OsString}, ++ os::unix::ffi::OsStrExt, + path::{Path, PathBuf}, + }; + +-use anyhow::{Context, Result}; +-use indexmap::{IndexMap, IndexSet}; +-use log::debug; ++use anyhow::{bail, Context, Result}; ++use indexmap::IndexSet; + use which::which; + +-use syscare_common::{ffi::OsStrExt, fs, process::Command}; ++use syscare_common::{concat_os, ffi::OsStrExt as _, fs, process::Command}; + +-use crate::dwarf::{Dwarf, ProducerType}; +- +-const STD_NAMES: [&str; 45] = [ +- "c89", "c90", "c99", "c9x", "c11", "c17", "c18", "c1x", "c2x", "gnu", "gnu89", "gnu90", +- "gnu99", "gnu9x", "gnu11", "gnu17", "gnu18", "gnu1x", "gnu2x", "c++98", "c++03", "c++0x", +- "c++11", "c++14", "c++17", "c++1y", "c++1z", "c++20", "c++2a", "gnu++98", "gnu++03", "gnu++0x", +- "gnu++11", "gnu++14", "gnu++17", "gnu++1y", "gnu++1z", "gnu++20", "gnu++2a", "f95", "f2003", +- "f2008", "f2008ts", "f2018", "legacy", +-]; +-const ASSEMBLER_NAME: &str = "as"; +-const LINKER_NAME: &str = "ld"; ++use crate::dwarf::{Producer, ProducerParser, ProducerType}; + + #[derive(Debug, Clone)] +-pub struct CompilerInfo { +- pub binary: PathBuf, +- pub assembler: PathBuf, ++pub struct Compiler { ++ pub prefix: Option, ++ pub name: OsString, ++ pub kind: ProducerType, ++ pub version: OsString, ++ pub path: PathBuf, + pub linker: PathBuf, +- pub producers: IndexSet, + } + +-impl CompilerInfo { +- fn get_component_name>(compiler: P, name: &str) -> Result { +- let output = Command::new(compiler.as_ref()) +- .arg(format!("-print-prog-name={}", name)) +- .run_with_output()?; +- +- output.exit_ok()?; +- Ok(output.stdout) +- } +- +- fn build_test_objects( +- binary: P, +- assembler: Q, +- output_dir: R, +- ) -> Result> ++impl Compiler { ++ pub fn parse(path: P, output_dir: Q) -> Result + where + P: AsRef, + Q: AsRef, +- R: AsRef, + { +- let source_file = output_dir.as_ref().join("test.c"); +- let assembly_file = output_dir.as_ref().join("test.S"); +- let assembly_object = output_dir.as_ref().join("test.o"); +- +- fs::write(&source_file, "int main() { return 0; }")?; ++ let path = path.as_ref().to_path_buf(); ++ let name = path ++ .file_name() ++ .context("Failed to parse compiler name")? ++ .to_os_string(); ++ ++ let output_path = Self::build_test_object(&path, &name, output_dir.as_ref()) ++ .context("Failed to build test object")?; ++ let prefix = Self::parse_compiler_prefix(&name).map(OsStr::to_os_string); ++ let producer = Self::parse_compiler_producer(&output_path) ++ .context("Failed to parse compiler producer")?; ++ let linker = Self::get_compiler_linker(&path, &prefix, &producer) ++ .context("Failed to get compiler linker")?; ++ ++ Ok(Self { ++ prefix, ++ name, ++ kind: producer.kind, ++ version: producer.version, ++ path, ++ linker, ++ }) ++ } + +- let mut object_files = IndexSet::new(); ++ fn build_test_object(path: &Path, name: &OsStr, output_dir: &Path) -> Result { ++ let source_file = output_dir.join("test.c"); ++ let output_file = output_dir.join(concat_os!(name, "-test")); + +- Command::new(binary.as_ref()) +- .arg("-S") ++ if !source_file.exists() { ++ fs::write(&source_file, "int main() { return 0; }")?; ++ } ++ Command::new(path) ++ .arg("-g") + .arg(&source_file) + .arg("-o") +- .arg(&assembly_file) ++ .arg(&output_file) + .run()? + .exit_ok()?; + +- Command::new(assembler.as_ref()) +- .arg("-g") +- .arg(assembly_file) +- .arg("-o") +- .arg(&assembly_object) +- .run()? +- .exit_ok()?; ++ Ok(output_file) ++ } ++ ++ fn parse_compiler_prefix(compiler: &OsStr) -> Option<&OsStr> { ++ /* ++ * Matches compiler prefix of compiler name ++ * eg. x86_64-linux-gnu-gcc -> x86_64-linux-gnu- ++ * eg. aarch64-target-linux-clang -> aarch64-target-linux- ++ */ ++ let slice = compiler.as_bytes(); ++ ++ let spliter_indices = slice.iter().enumerate().rev().filter_map(|(index, &b)| { ++ if b == b'-' { ++ return Some(index); ++ } ++ None ++ }); + +- object_files.insert(assembly_object); +- +- for std_name in STD_NAMES { +- let compiler_object = output_dir.as_ref().join(format!("test_{}.o", std_name)); +- let build_success = Command::new(binary.as_ref()) +- .arg(format!("-std={}", std_name)) +- .args(["-g", "-c"]) +- .arg(&source_file) +- .arg("-o") +- .arg(&compiler_object) +- .stderr(log::Level::Trace) +- .run_with_output()? +- .success(); +- +- if build_success { +- object_files.insert(compiler_object); ++ for pos in spliter_indices { ++ let (prefix, name) = slice.split_at(pos + 1); ++ if name.iter().any(|&b| !b.is_ascii_digit()) { ++ return Some(OsStr::from_bytes(prefix)); + } + } +- object_files.sort(); + +- Ok(object_files) ++ None + } + +- fn run_compiler_detection( +- binary: P, +- assembler: Q, +- output_dir: R, +- ) -> Result> +- where +- P: AsRef, +- Q: AsRef, +- R: AsRef, +- { +- let mut producers = IndexSet::new(); +- +- let test_objects = Self::build_test_objects(binary, assembler, &output_dir) +- .context("Failed to build test objects")?; +- for test_object in test_objects { +- producers.extend(Dwarf::parse(test_object)?.producers()); ++ fn parse_compiler_producer(path: &Path) -> Result { ++ let producer_parser = ProducerParser::open(path) ++ .with_context(|| format!("Failed to open {}", path.display()))?; ++ let producer_iter = producer_parser ++ .parse() ++ .with_context(|| format!("Failed to parse {}", path.display()))?; ++ ++ let mut producer_map = IndexSet::new(); ++ for parse_result in producer_iter { ++ let producer = parse_result.context("Failed to parse object producer")?; ++ producer_map.insert(producer); + } +- producers.sort(); ++ producer_map.sort(); + +- fs::remove_dir_all(&output_dir)?; +- Ok(producers) ++ // Compiler producer would be highest supported. ++ producer_map.pop().context("No object producer") + } +-} + +-impl CompilerInfo { +- pub fn parse(compilers: I, temp_dir: Q) -> Result> +- where +- I: IntoIterator, +- P: AsRef, +- Q: AsRef, +- { +- let mut compiler_map = IndexMap::new(); +- +- for compiler in compilers { +- let binary_file = compiler.as_ref(); +- let binary_name = binary_file +- .file_name() +- .context("Failed to parse binary name")?; +- +- let output_dir = temp_dir.as_ref().join(binary_name); +- fs::create_dir_all(&output_dir)?; +- +- debug!("- Checking {}", binary_file.display()); +- let assembler_name = Self::get_component_name(binary_file, ASSEMBLER_NAME) +- .with_context(|| { +- format!("Failed to get assembler name of {}", binary_file.display()) +- })?; +- let assembler = fs::normalize(which(assembler_name.trim()).with_context(|| { +- format!("Cannot find assembler {}", assembler_name.to_string_lossy()) +- })?)?; +- +- let linker_name = +- Self::get_component_name(binary_file, LINKER_NAME).with_context(|| { +- format!("Failed to get linker name of {}", binary_file.display()) +- })?; +- let linker = fs::normalize(which(linker_name.trim()).with_context(|| { +- format!("Cannot find linker {}", linker_name.to_string_lossy()) +- })?)?; +- let producers = Self::run_compiler_detection(&compiler, &assembler, &output_dir) +- .context("Failed to detect compiler")?; +- +- for producer in &producers { +- let producer_type = ProducerType::from(producer); +- if (producer_type == ProducerType::As) || (producer_type == ProducerType::Unknown) { +- continue; +- } +- compiler_map.insert( +- producer_type, +- Self { +- binary: binary_file.to_path_buf(), +- assembler: assembler.clone(), +- linker: linker.clone(), +- producers: producers.clone(), +- }, +- ); ++ fn get_component( ++ path: &Path, ++ prefix: &Option, ++ name: &str, ++ ) -> Result> { ++ let get_component_path = |name: &OsStr| -> Result> { ++ let output = Command::new(path) ++ .arg(concat_os!("-print-prog-name=", name)) ++ .run_with_output()?; ++ output.exit_ok()?; ++ Ok(which(output.stdout.trim()).ok()) ++ }; ++ ++ if let Some(prefixed_name) = prefix.as_ref().map(|pfx| concat_os!(pfx, name)) { ++ let component = get_component_path(&prefixed_name)?; ++ if component.is_some() { ++ return Ok(component); + } + } +- compiler_map.sort_keys(); ++ get_component_path(OsStr::new(name)) ++ } ++ ++ fn get_compiler_linker( ++ path: &Path, ++ prefix: &Option, ++ producer: &Producer, ++ ) -> Result { ++ const CLANG_LINKER_NAMES: &[&str] = &["ld.lld", "ld"]; ++ const GNU_LINKER_NAMES: &[&str] = &["ld"]; ++ ++ let linkers = if matches!(producer.kind, ProducerType::ClangC | ProducerType::ClangCxx) { ++ // Clang may use llvm linker, we will try it firstly. ++ CLANG_LINKER_NAMES ++ } else { ++ GNU_LINKER_NAMES ++ }; ++ for name in linkers { ++ if let Some(path) = Self::get_component(path, prefix, name)? { ++ return Ok(path); ++ } ++ } ++ bail!("No suitable linker") ++ } ++} + +- Ok(compiler_map) ++impl std::fmt::Display for Compiler { ++ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { ++ f.write_fmt(format_args!( ++ "{}{}", ++ self.prefix.as_deref().unwrap_or_default().to_string_lossy(), ++ self.name.to_string_lossy() ++ )) + } + } +diff --git a/upatch-build/src/dwarf.rs b/upatch-build/src/dwarf.rs +new file mode 100644 +index 0000000..c93cfa9 +--- /dev/null ++++ b/upatch-build/src/dwarf.rs +@@ -0,0 +1,379 @@ ++use std::{ ++ cell::RefCell, ++ collections::HashMap, ++ ffi::{OsStr, OsString}, ++ os::unix::ffi::OsStrExt, ++ path::Path, ++ rc::Rc, ++}; ++ ++use anyhow::{bail, Context, Result}; ++use gimli::{ ++ constants::*, AttributeValue, DebugInfoUnitHeadersIter, DebuggingInformationEntry, DwLang, ++ Dwarf, EndianRcSlice, Endianity, Reader, RunTimeEndian, SectionId, Unit, UnitOffset, ++}; ++use memmap2::Mmap; ++use object::{Endianness, Object, ObjectSection, ObjectSymbol, RelocationKind, RelocationTarget}; ++use once_cell::sync::Lazy; ++use regex::bytes::Regex; ++ ++#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] ++pub enum ProducerType { ++ GnuAs, ++ LlvmAs, ++ GnuC, ++ ClangC, ++ GnuCxx, ++ ClangCxx, ++ Unknown, ++} ++ ++impl std::fmt::Display for ProducerType { ++ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { ++ let name = match self { ++ ProducerType::GnuAs => "GNU AS", ++ ProducerType::LlvmAs => "LLVM AS", ++ ProducerType::GnuC => "GNU C", ++ ProducerType::ClangC => "Clang C", ++ ProducerType::GnuCxx => "GNU C++", ++ ProducerType::ClangCxx => "Clang C++", ++ ProducerType::Unknown => "Unknown", ++ }; ++ f.write_str(name) ++ } ++} ++ ++#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] ++pub struct Producer { ++ pub kind: ProducerType, ++ pub name: OsString, ++ pub version: OsString, ++} ++ ++impl Producer { ++ pub fn is_assembler(&self) -> bool { ++ matches!(self.kind, ProducerType::GnuAs | ProducerType::LlvmAs) ++ } ++} ++ ++impl std::fmt::Display for Producer { ++ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { ++ f.write_fmt(format_args!( ++ "{} {}", ++ self.name.to_string_lossy(), ++ self.version.to_string_lossy() ++ )) ++ } ++} ++ ++pub struct ProducerParser { ++ _file: std::fs::File, ++ mmap: Mmap, ++ data_map: RefCell>>, ++} ++ ++impl ProducerParser { ++ pub fn open>(path: P) -> Result { ++ let _file = std::fs::File::open(path)?; ++ let mmap = unsafe { Mmap::map(&_file)? }; ++ mmap.advise(memmap2::Advice::Random)?; ++ ++ Ok(Self { ++ _file, ++ mmap, ++ data_map: RefCell::new(HashMap::new()), ++ }) ++ } ++ ++ pub fn parse(&self) -> Result + '_>> { ++ let dwarf = Dwarf::load(|section_id| -> Result<_> { self.load_section(section_id) }) ++ .context("Failed to load DWARF information")?; ++ let headers = dwarf.units(); ++ ++ Ok(ProducerIterator { ++ dwarf, ++ headers, ++ state: None, ++ }) ++ } ++} ++ ++impl ProducerParser { ++ fn load_section(&self, section_id: SectionId) -> Result + '_> { ++ const U8_TYPE_SIZE: usize = 1; ++ const U16_TYPE_SIZE: usize = 2; ++ const U32_TYPE_SIZE: usize = 4; ++ const U64_TYPE_SIZE: usize = 8; ++ const BYTE_BIT_NUM: u8 = 8; ++ ++ let file = object::File::parse(self.mmap.as_ref())?; ++ let endian = match file.endianness() { ++ Endianness::Little => RunTimeEndian::Little, ++ Endianness::Big => RunTimeEndian::Big, ++ }; ++ ++ let section_name = section_id.name(); ++ let section = match file.section_by_name(section_name) { ++ Some(section) => section, ++ None => return Ok(EndianRcSlice::new(Rc::default(), endian)), ++ }; ++ ++ let mut section_data = section ++ .uncompressed_data() ++ .map(|slice| slice.into_owned()) ++ .with_context(|| format!("Failed to read section {}", section_name))?; ++ for (offset, reloc) in section.relocations() { ++ if let RelocationTarget::Symbol(index) = reloc.target() { ++ if !matches!(reloc.kind(), RelocationKind::Absolute) { ++ continue; ++ } ++ ++ let symbol = file.symbol_by_index(index)?; ++ let addend = reloc.addend(); ++ let value = if addend >= 0 { ++ symbol.address().checked_add(addend.unsigned_abs()) ++ } else { ++ symbol.address().checked_sub(addend.unsigned_abs()) ++ } ++ .context("Relocation overflow")?; ++ ++ let len = (reloc.size() / BYTE_BIT_NUM) as usize; ++ let buf = &mut section_data[offset as usize..offset as usize + len]; ++ ++ match len { ++ U8_TYPE_SIZE => buf[0] = value as u8, ++ U16_TYPE_SIZE => endian.write_u16(buf, value as u16), ++ U32_TYPE_SIZE => endian.write_u32(buf, value as u32), ++ U64_TYPE_SIZE => endian.write_u64(buf, value), ++ _ => bail!("Invalid relocation length"), ++ } ++ } else { ++ bail!("Unsupported relocation type"); ++ } ++ } ++ ++ let bytes: Rc<[u8]> = Rc::from(section_data.into_boxed_slice()); ++ self.data_map.borrow_mut().insert(section_id, bytes.clone()); ++ ++ Ok(EndianRcSlice::new(bytes, endian)) ++ } ++ ++ fn parse_producer_attr( ++ dwarf: &Dwarf, ++ unit: &Unit, ++ attr: AttributeValue, ++ ) -> Result ++ where ++ R: Reader, ++ { ++ let attr = dwarf ++ .attr_string(unit, attr) ++ .context("Cannot find attribute string")?; ++ let slice = attr ++ .to_slice() ++ .context("Failed to read attribute string data")?; ++ ++ Ok(OsStr::from_bytes(&slice).to_os_string()) ++ } ++ ++ fn parse_producer_name(str: &OsStr) -> Option<&OsStr> { ++ /* ++ * Matches name in producer string ++ * eg. GNU C17 12.3.1 (openEuler 12.3.1-62.oe2403sp1) -> GNU C17 ++ * eg. clang version 17.0.6 (17.0.6-30-oe2043sp1) -> clang ++ */ ++ static PRODUCER_NAME_REGEX: Lazy = Lazy::new(|| { ++ Regex::new(r"^((?:\s?[A-Za-z]+\d*)+)").expect("Invalid producer name regex") ++ }); ++ ++ PRODUCER_NAME_REGEX ++ .captures(str.as_bytes()) ++ .and_then(|captures| captures.get(1)) ++ .map(|matched| matched.as_bytes()) ++ .map(|bytes| bytes.strip_suffix(b" version").unwrap_or(bytes)) ++ .map(OsStr::from_bytes) ++ } ++ ++ fn parse_producer_version(str: &OsStr) -> Option<&OsStr> { ++ /* ++ * Matches version in producer string ++ * eg. GNU C17 12.3.1 (openEuler 12.3.1-62.oe2403sp1) -> 12.3.1 ++ * eg. clang version 17.0.6 (17.0.6-30-oe2043sp1) -> 17.0.6 ++ */ ++ static PRODUCER_VERSION_REGEX: Lazy = ++ Lazy::new(|| Regex::new(r"(\d+(?:\.\d+)+)").expect("Invalid producer version regex")); ++ ++ PRODUCER_VERSION_REGEX ++ .captures(str.as_bytes()) ++ .and_then(|captures| captures.get(1)) ++ .map(|matched| matched.as_bytes()) ++ .map(OsStr::from_bytes) ++ } ++ ++ fn parse_producer_type(str: &OsStr, attr: AttributeValue) -> Result ++ where ++ R: Reader, ++ { ++ const DW_LANGS_AS: &[DwLang] = &[ ++ DW_LANG_Mips_Assembler, ++ DW_LANG_SUN_Assembler, ++ DW_LANG_ALTIUM_Assembler, ++ ]; ++ const DW_LANGS_C: &[DwLang] = &[ ++ DW_LANG_C, ++ DW_LANG_C89, ++ DW_LANG_C99, ++ DW_LANG_C11, ++ DW_LANG_C17, ++ ]; ++ const DW_LANGS_CXX: &[DwLang] = &[ ++ DW_LANG_C_plus_plus, ++ DW_LANG_C_plus_plus_03, ++ DW_LANG_C_plus_plus_11, ++ DW_LANG_C_plus_plus_14, ++ DW_LANG_C_plus_plus_17, ++ DW_LANG_C_plus_plus_20, ++ ]; ++ const GNU_PRODUCER_PREFIX: &str = "GNU"; ++ ++ let lang = match attr { ++ AttributeValue::Language(lang) => lang, ++ _ => bail!("Unexpected attribute type"), ++ }; ++ let is_gnu = str.to_string_lossy().starts_with(GNU_PRODUCER_PREFIX); ++ let kind = match lang { ++ lang if DW_LANGS_AS.contains(&lang) => { ++ if is_gnu { ++ ProducerType::GnuAs ++ } else { ++ ProducerType::LlvmAs ++ } ++ } ++ lang if DW_LANGS_C.contains(&lang) => { ++ if is_gnu { ++ ProducerType::GnuC ++ } else { ++ ProducerType::ClangC ++ } ++ } ++ lang if DW_LANGS_CXX.contains(&lang) => { ++ if is_gnu { ++ ProducerType::GnuCxx ++ } else { ++ ProducerType::ClangCxx ++ } ++ } ++ _ => ProducerType::Unknown, ++ }; ++ ++ Ok(kind) ++ } ++ ++ fn parse_producer( ++ dwarf: &Dwarf, ++ unit: &Unit, ++ die: DebuggingInformationEntry, ++ ) -> Result> ++ where ++ R: Reader, ++ { ++ if die.tag() != DW_TAG_compile_unit { ++ return Ok(None); ++ } ++ ++ let str = match die.attr_value(DW_AT_producer)? { ++ Some(attr) => Self::parse_producer_attr(dwarf, unit, attr)?, ++ None => bail!("Invalid DW_AT_producer attribute"), ++ }; ++ let kind = match die.attr_value(DW_AT_language)? { ++ Some(attr) => Self::parse_producer_type(&str, attr)?, ++ _ => bail!("Invalid DW_AT_language attribute"), ++ }; ++ let name = Self::parse_producer_name(&str).context("Invalid producer name")?; ++ let version = Self::parse_producer_version(&str).context("Invalid producer version")?; ++ ++ Ok(Some(Producer { ++ kind, ++ name: name.to_os_string(), ++ version: version.to_os_string(), ++ })) ++ } ++} ++ ++pub struct ProducerIterator { ++ dwarf: Dwarf, ++ headers: DebugInfoUnitHeadersIter, ++ state: Option<(Unit, Vec)>, ++} ++ ++impl> ProducerIterator { ++ fn current(&self) -> Result, DebuggingInformationEntry)>> { ++ if let Some((unit, offsets)) = &self.state { ++ if let Some(offset) = offsets.last() { ++ return Ok(Some((unit, unit.entry(*offset)?))); ++ } ++ } ++ Ok(None) ++ } ++ ++ fn has_die(&self) -> bool { ++ self.state ++ .as_ref() ++ .map(|(_, offsets)| !offsets.is_empty()) ++ .unwrap_or(false) ++ } ++ ++ fn next_die(&mut self) { ++ if let Some((_, offsets)) = &mut self.state { ++ offsets.pop(); ++ } ++ } ++ ++ fn next_unit(&mut self) -> Result<()> { ++ if let Some(header) = self.headers.next()? { ++ let unit = self.dwarf.unit(header)?; ++ ++ let mut offsets = Vec::new(); ++ let mut cursor = unit.entries(); ++ while let Some((_, entry)) = cursor.next_dfs()? { ++ offsets.push(entry.offset()); ++ } ++ offsets.reverse(); ++ ++ self.state = Some((unit, offsets)); ++ } ++ ++ Ok(()) ++ } ++} ++ ++impl> Iterator for ProducerIterator { ++ type Item = Result; ++ ++ fn next(&mut self) -> Option { ++ loop { ++ let producer = match self.current() { ++ Ok(Some((unit, die))) => { ++ ProducerParser::parse_producer(&self.dwarf, unit, die).transpose() ++ } ++ Ok(None) => None, ++ Err(e) => Some(Err(e)), ++ }; ++ ++ self.next_die(); ++ ++ if producer.is_some() { ++ return producer; ++ } ++ ++ if !self.has_die() { ++ if let Err(e) = self.next_unit() { ++ return Some(Err(e)); ++ } ++ if !self.has_die() { ++ return None; ++ } ++ } ++ } ++ } ++} +diff --git a/upatch-build/src/dwarf/mod.rs b/upatch-build/src/dwarf/mod.rs +deleted file mode 100644 +index 4399b51..0000000 +--- a/upatch-build/src/dwarf/mod.rs ++++ /dev/null +@@ -1,274 +0,0 @@ +-// SPDX-License-Identifier: Mulan PSL v2 +-/* +- * Copyright (c) 2024 Huawei Technologies Co., Ltd. +- * upatch-build is licensed under Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. +- * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +- * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +- * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +- * See the Mulan PSL v2 for more details. +- */ +- +-// mod dump; +-mod relocate; +- +-use std::{ +- borrow::{Borrow, Cow}, +- ffi::{OsStr, OsString}, +- os::unix::ffi::OsStrExt as UnixOsStrExt, +- path::{Path, PathBuf}, +-}; +- +-use anyhow::Result; +-use gimli::{ +- constants, Attribute, AttributeValue, EndianSlice, Endianity, Reader, RunTimeEndian, SectionId, +-}; +-use indexmap::{IndexMap, IndexSet}; +-use log::trace; +-use object::{ +- File, Object, ObjectSection, ObjectSymbol, Relocation, RelocationKind, RelocationTarget, +- Section, +-}; +-use typed_arena::Arena; +- +-use syscare_common::{ffi::OsStrExt, fs::MappedFile}; +- +-use relocate::Relocate; +- +-#[allow(non_snake_case)] +-#[derive(Debug, Clone, Hash, PartialEq, Eq)] +-pub struct CompileUnit { +- producer: OsString, // DW_AT_producer +- compile_dir: PathBuf, // DW_AT_comp_dir +- file_name: PathBuf, // DW_AT_name +-} +- +-impl CompileUnit { +- pub fn producer(&self) -> OsString { +- self.producer +- .split('-') +- .next() +- .map(|s| s.trim().to_os_string()) +- .unwrap_or_else(|| self.producer.clone()) +- } +- +- pub fn producer_type(&self) -> ProducerType { +- ProducerType::from(&self.producer) +- } +-} +- +-#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +-pub enum ProducerType { +- C, +- Cxx, +- As, +- Unknown, +-} +- +-impl> From for ProducerType { +- fn from(s: S) -> Self { +- if s.as_ref().contains("C++") { +- ProducerType::Cxx +- } else if s.as_ref().contains("C") { +- ProducerType::C +- } else if s.as_ref().contains("AS") { +- ProducerType::As +- } else { +- ProducerType::Unknown +- } +- } +-} +- +-impl std::fmt::Display for ProducerType { +- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +- f.write_str(match self { +- ProducerType::C => "C", +- ProducerType::Cxx => "CXX", +- ProducerType::As => "AS", +- ProducerType::Unknown => "Unknown", +- }) +- } +-} +- +-pub struct Dwarf { +- pub units: IndexSet, +-} +- +-impl Dwarf { +- pub fn parse>(file_path: P) -> Result { +- let mmap = MappedFile::open(file_path)?; +- let object = File::parse(mmap.as_bytes())?; +- let endian = if object.is_little_endian() { +- gimli::RunTimeEndian::Little +- } else { +- gimli::RunTimeEndian::Big +- }; +- +- Ok(Self { +- units: Self::parse_compile_units(&object, endian)?, +- }) +- } +- +- pub fn producers(&self) -> IndexSet { +- self.units.iter().map(|unit| unit.producer()).collect() +- } +- +- pub fn producer_types(&self) -> IndexSet { +- self.units.iter().map(|unit| unit.producer_type()).collect() +- } +-} +- +-impl Dwarf { +- fn add_relocations( +- relocations: &mut IndexMap, +- file: &File, +- section: &Section, +- ) { +- const INVALID_SECTION_NAME: &str = ".invalid"; +- +- for (offset64, mut relocation) in section.relocations() { +- let offset = offset64 as usize; +- if offset as u64 != offset64 { +- continue; +- } +- match relocation.kind() { +- RelocationKind::Absolute => { +- if let RelocationTarget::Symbol(symbol_idx) = relocation.target() { +- match file.symbol_by_index(symbol_idx) { +- Ok(symbol) => { +- let addend = +- symbol.address().wrapping_add(relocation.addend() as u64); +- relocation.set_addend(addend as i64); +- } +- Err(_) => { +- trace!("Relocation with invalid symbol for section {} at offset 0x{:08x}", +- section.name().unwrap_or(INVALID_SECTION_NAME), offset +- ); +- } +- } +- } +- if relocations.insert(offset, relocation).is_some() { +- trace!( +- "Multiple relocations for section {} at offset 0x{:08x}", +- section.name().unwrap_or(INVALID_SECTION_NAME), +- offset +- ); +- } +- } +- _ => { +- trace!( +- "Unsupported relocation for section {} at offset 0x{:08x}", +- section.name().unwrap_or(INVALID_SECTION_NAME), +- offset +- ); +- } +- } +- } +- } +- +- fn load_file_section<'input, 'arena, Endian: Endianity>( +- id: SectionId, +- file: &File<'input>, +- endian: Endian, +- arena_data: &'arena Arena>, +- arena_relocations: &'arena Arena>, +- ) -> Result>> { +- let mut relocation_map = IndexMap::new(); +- let name = Some(id.name()); +- let data = match name.and_then(|section_name| file.section_by_name(section_name)) { +- Some(ref section) => { +- // DWO sections never have relocations, so don't bother. +- Self::add_relocations(&mut relocation_map, file, section); +- section.uncompressed_data()? +- } +- // Use a non-zero capacity so that `ReaderOffsetId`s are unique. +- None => Cow::Owned(Vec::with_capacity(1)), +- }; +- let data_ref = (*arena_data.alloc(data)).borrow(); +- let reader = EndianSlice::new(data_ref, endian); +- let section = reader; +- let relocations = (*arena_relocations.alloc(relocation_map)).borrow(); +- Ok(Relocate { +- relocations, +- section, +- reader, +- }) +- } +- +- fn parse_compile_units(file: &File, endian: RunTimeEndian) -> Result> { +- let arena_data = Arena::new(); +- let arena_relocations = Arena::new(); +- +- // Load a section and return as `Cow<[u8]>`. +- let mut load_section = |id: SectionId| -> Result<_> { +- Self::load_file_section(id, file, endian, &arena_data, &arena_relocations) +- }; +- +- let dwarf = gimli::Dwarf::load(&mut load_section)?; +- +- Self::build_compile_units(&dwarf) +- } +- +- fn build_compile_units(dwarf: &gimli::Dwarf) -> Result> { +- let mut result = IndexSet::new(); +- let mut iter = dwarf.units(); +- while let Some(header) = iter.next()? { +- let unit = dwarf.unit(header)?; +- let mut entries = unit.entries(); +- while let Some((_, entry)) = entries.next_dfs()? { +- if entry.tag() != constants::DW_TAG_compile_unit { +- break; +- } +- // Iterate over the attributes in the DIE. +- let mut attrs = entry.attrs(); +- let mut element = CompileUnit { +- producer: OsString::new(), +- compile_dir: PathBuf::new(), +- file_name: PathBuf::new(), +- }; +- +- while let Some(attr) = attrs.next()? { +- match attr.name() { +- constants::DW_AT_comp_dir => { +- element.compile_dir.push(Self::attr_value(&attr, dwarf)); +- } +- constants::DW_AT_name => { +- element.file_name.push(Self::attr_value(&attr, dwarf)); +- } +- constants::DW_AT_producer => { +- element.producer.push(Self::attr_value(&attr, dwarf)); +- } +- _ => continue, +- } +- } +- +- result.insert(element); +- } +- } +- Ok(result) +- } +- +- fn attr_value(attr: &Attribute, dwarf: &gimli::Dwarf) -> OsString { +- let value = attr.value(); +- match value { +- AttributeValue::DebugLineStrRef(offset) => { +- if let Ok(s) = dwarf.debug_line_str.get_str(offset) { +- OsStr::from_bytes(&s.to_slice().ok().unwrap_or_default()).to_os_string() +- } else { +- OsString::default() +- } +- } +- AttributeValue::DebugStrRef(offset) => { +- if let Ok(s) = dwarf.debug_str.get_str(offset) { +- OsStr::from_bytes(&s.to_slice().ok().unwrap_or_default()).to_os_string() +- } else { +- OsString::default() +- } +- } +- _ => OsString::default(), +- } +- } +-} +diff --git a/upatch-build/src/dwarf/relocate.rs b/upatch-build/src/dwarf/relocate.rs +deleted file mode 100644 +index a6e8fb9..0000000 +--- a/upatch-build/src/dwarf/relocate.rs ++++ /dev/null +@@ -1,146 +0,0 @@ +-// SPDX-License-Identifier: Mulan PSL v2 +-/* +- * Copyright (c) 2024 Huawei Technologies Co., Ltd. +- * upatch-build is licensed under Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. +- * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +- * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +- * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +- * See the Mulan PSL v2 for more details. +- */ +- +-use std::borrow::Cow; +- +-use gimli::ReaderOffset; +-use indexmap::IndexMap; +-use object::Relocation; +- +-#[derive(Debug, Clone)] +-pub struct Relocate<'a, R: gimli::Reader> { +- pub relocations: &'a IndexMap, +- pub section: R, +- pub reader: R, +-} +- +-impl> Relocate<'_, R> { +- pub fn relocate(&self, offset: usize, value: u64) -> u64 { +- if let Some(relocation) = self.relocations.get(&offset) { +- if relocation.kind() == object::RelocationKind::Absolute { +- return if relocation.has_implicit_addend() { +- // Use the explicit addend too, because it may have the symbol value. +- value.wrapping_add(relocation.addend() as u64) +- } else { +- relocation.addend() as u64 +- }; +- } +- }; +- value +- } +-} +- +-impl> gimli::Reader for Relocate<'_, R> { +- type Endian = R::Endian; +- type Offset = R::Offset; +- +- fn read_address(&mut self, address_size: u8) -> gimli::Result { +- let offset = self.reader.offset_from(&self.section); +- let value = self.reader.read_address(address_size)?; +- Ok(self.relocate(offset, value)) +- } +- +- fn read_length(&mut self, format: gimli::Format) -> gimli::Result { +- let offset = self.reader.offset_from(&self.section); +- let value = self.reader.read_length(format)?; +- gimli::ReaderOffset::from_u64(self.relocate(offset, value.into_u64())) +- } +- +- fn read_offset(&mut self, format: gimli::Format) -> gimli::Result { +- let offset = self.reader.offset_from(&self.section); +- let value = self.reader.read_offset(format)?; +- gimli::ReaderOffset::from_u64(self.relocate(offset, value.into_u64())) +- } +- +- fn read_sized_offset(&mut self, size: u8) -> gimli::Result { +- let offset = self.reader.offset_from(&self.section); +- let value = self.reader.read_sized_offset(size)?; +- gimli::ReaderOffset::from_u64(self.relocate(offset, value.into_u64())) +- } +- +- #[inline] +- fn split(&mut self, len: Self::Offset) -> gimli::Result { +- let mut other = self.clone(); +- other.reader.truncate(len)?; +- self.reader.skip(len)?; +- Ok(other) +- } +- +- // All remaining methods simply delegate to `self.reader`. +- +- #[inline] +- fn endian(&self) -> Self::Endian { +- self.reader.endian() +- } +- +- #[inline] +- fn len(&self) -> Self::Offset { +- self.reader.len() +- } +- +- #[inline] +- fn empty(&mut self) { +- self.reader.empty() +- } +- +- #[inline] +- fn truncate(&mut self, len: Self::Offset) -> gimli::Result<()> { +- self.reader.truncate(len) +- } +- +- #[inline] +- fn offset_from(&self, base: &Self) -> Self::Offset { +- self.reader.offset_from(&base.reader) +- } +- +- #[inline] +- fn offset_id(&self) -> gimli::ReaderOffsetId { +- self.reader.offset_id() +- } +- +- #[inline] +- fn lookup_offset_id(&self, id: gimli::ReaderOffsetId) -> Option { +- self.reader.lookup_offset_id(id) +- } +- +- #[inline] +- fn find(&self, byte: u8) -> gimli::Result { +- self.reader.find(byte) +- } +- +- #[inline] +- fn skip(&mut self, len: Self::Offset) -> gimli::Result<()> { +- self.reader.skip(len) +- } +- +- #[inline] +- fn to_slice(&self) -> gimli::Result> { +- self.reader.to_slice() +- } +- +- #[inline] +- fn to_string(&self) -> gimli::Result> { +- self.reader.to_string() +- } +- +- #[inline] +- fn to_string_lossy(&self) -> gimli::Result> { +- self.reader.to_string_lossy() +- } +- +- #[inline] +- fn read_slice(&mut self, buf: &mut [u8]) -> gimli::Result<()> { +- self.reader.read_slice(buf) +- } +-} +diff --git a/upatch-build/src/main.rs b/upatch-build/src/main.rs +index 73d286f..56a8715 100644 +--- a/upatch-build/src/main.rs ++++ b/upatch-build/src/main.rs +@@ -12,15 +12,23 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{env, ffi::OsStr, fs::Permissions, os::unix::fs::PermissionsExt, path::Path, process}; ++use std::{ ++ env, ++ ffi::OsStr, ++ fs::Permissions, ++ os::unix::fs::PermissionsExt, ++ path::{Path, PathBuf}, ++ process, ++}; + +-use anyhow::{ensure, Context, Result}; ++use anyhow::{bail, ensure, Context, Result}; + use flexi_logger::{ + DeferredNow, Duplicate, FileSpec, LogSpecification, Logger, LoggerHandle, WriteMode, + }; + use indexmap::{IndexMap, IndexSet}; + use log::{debug, error, info, trace, warn, Level, LevelFilter, Record}; + use object::{write, Object, ObjectKind, ObjectSection, SectionKind}; ++ + use syscare_common::{ + concat_os, + fs::{self, MappedFile}, +@@ -37,12 +45,14 @@ mod file_relation; + mod project; + mod resolve; + +-use args::Arguments; +-use build_root::BuildRoot; +-use compiler::CompilerInfo; +-use dwarf::{Dwarf, ProducerType}; +-use file_relation::FileRelation; +-use project::Project; ++use crate::{ ++ args::Arguments, ++ build_root::BuildRoot, ++ compiler::Compiler, ++ dwarf::{ProducerParser, ProducerType}, ++ file_relation::FileRelation, ++ project::Project, ++}; + + const CLI_NAME: &str = "upatch build"; + const CLI_VERSION: &str = env!("CARGO_PKG_VERSION"); +@@ -59,7 +69,7 @@ struct UpatchBuild { + args: Arguments, + logger: LoggerHandle, + build_root: BuildRoot, +- compiler_map: IndexMap, ++ compiler_map: IndexMap, + file_relation: FileRelation, + } + +@@ -107,25 +117,101 @@ impl UpatchBuild { + }) + } + +- fn check_debuginfo(&self) -> Result<()> { +- let supported_compilers = self +- .compiler_map +- .values() +- .flat_map(|info| &info.producers) +- .collect::>(); +- for debuginfo in &self.args.debuginfo { +- for producer in Dwarf::parse(debuginfo)?.producers() { +- ensure!( +- supported_compilers.contains(&producer), +- "{} is not supported", +- producer.to_string_lossy() +- ); ++ fn detect_compilers(&mut self) -> Result<()> { ++ let mut c_compilers = 0usize; ++ let mut cxx_compilers = 0usize; ++ ++ for compiler_path in &self.args.compiler { ++ let compiler = Compiler::parse(compiler_path, &self.build_root.build_dir) ++ .with_context(|| format!("Failed to detect {}", compiler_path.display()))?; ++ match compiler.kind { ++ ProducerType::GnuC | ProducerType::ClangC => c_compilers += 1, ++ ProducerType::GnuCxx | ProducerType::ClangCxx => cxx_compilers += 1, ++ _ => bail!("Unknown compiler type"), + } ++ info!( ++ "[{}] name: {}, version: {}", ++ compiler.kind, ++ compiler, ++ compiler.version.to_string_lossy(), ++ ); ++ self.compiler_map.insert(compiler.kind, compiler); + } + ++ ensure!( ++ c_compilers <= 1 && cxx_compilers <= 1, ++ "Cannot define multiple C/C++ compilers" ++ ); ++ self.compiler_map.sort_keys(); ++ + Ok(()) + } + ++ fn check_compiler_version(&self) -> Result<()> { ++ for path in &self.args.debuginfo { ++ let producer_parser = ProducerParser::open(path) ++ .with_context(|| format!("Failed to open {}", path.display()))?; ++ let producer_iter = producer_parser ++ .parse() ++ .with_context(|| format!("Failed to parse {}", path.display()))?; ++ ++ for parse_result in producer_iter { ++ let producer = parse_result.context("Failed to parse debuginfo producer")?; ++ if producer.is_assembler() { ++ continue; ++ } ++ let matched = self ++ .compiler_map ++ .get(&producer.kind) ++ .map(|compiler| compiler.version == producer.version) ++ .unwrap_or(false); ++ ensure!(matched, "Producer {} mismatched", producer); ++ } ++ } ++ ++ Ok(()) ++ } ++ ++ fn find_linker(&self, objects: &[PathBuf]) -> Result<&Path> { ++ let mut producers = IndexSet::new(); ++ for path in objects { ++ let producer_parser = ProducerParser::open(path) ++ .with_context(|| format!("Failed to open {}", path.display()))?; ++ let producer_iter = producer_parser ++ .parse() ++ .with_context(|| format!("Failed to parse {}", path.display()))?; ++ ++ for parse_result in producer_iter { ++ let producer = parse_result.context("Failed to parse object producer")?; ++ if producer.is_assembler() { ++ continue; ++ } ++ producers.insert(producer); ++ } ++ } ++ producers.sort(); ++ ++ let producer = producers.pop().context("No object producer")?; ++ let compiler = self ++ .compiler_map ++ .get(&producer.kind) ++ .with_context(|| format!("Cannot find {} compiler", producer.kind))?; ++ ++ Ok(compiler.linker.as_path()) ++ } ++ ++ fn link_objects(&self, objects: &[PathBuf], output: &Path) -> Result<()> { ++ let linker = self.find_linker(objects).context("Cannot find linker")?; ++ ++ Command::new(linker) ++ .args(["-r", "-o"]) ++ .arg(output) ++ .args(objects) ++ .stdout(Level::Trace) ++ .run_with_output()? ++ .exit_ok() ++ } ++ + fn build_patch(&self, patch_name: &OsStr, binary: &Path, debuginfo: &Path) -> Result<()> { + const NOTES_OBJECT_NAME: &str = "notes.o"; + +@@ -170,9 +256,9 @@ impl UpatchBuild { + } + + debug!("- Collecting changes"); +- let mut changed_objects = +- elf::find_elf_files(&temp_dir, |_, obj_kind| obj_kind == ObjectKind::Relocatable)?; +- if changed_objects.is_empty() { ++ let mut objects = ++ elf::find_elf_files(&temp_dir, |_, kind| matches!(kind, ObjectKind::Relocatable))?; ++ if objects.is_empty() { + debug!("- No functional changes"); + return Ok(()); + } +@@ -181,25 +267,10 @@ impl UpatchBuild { + let notes_object = temp_dir.join(NOTES_OBJECT_NAME); + Self::create_note(&debuginfo_file, ¬es_object) + .context("Failed to create patch notes")?; +- changed_objects.push(notes_object); +- +- debug!("- Linking patch objects"); +- let mut link_compiler = ProducerType::C; +- for object in &changed_objects { +- if Dwarf::parse(object)? +- .producer_types() +- .contains(&ProducerType::Cxx) +- { +- link_compiler = ProducerType::Cxx; +- break; +- } +- } ++ objects.push(notes_object); + +- let compiler_info = self +- .compiler_map +- .get(&link_compiler) +- .with_context(|| format!("Failed to get link compiler {}", link_compiler))?; +- Self::link_objects(&compiler_info.linker, &changed_objects, &output_file) ++ debug!("- Linking patch"); ++ self.link_objects(&objects, &output_file) + .context("Failed to link patch objects")?; + + debug!("- Resolving patch"); +@@ -231,36 +302,16 @@ impl UpatchBuild { + } + + fn run(&mut self) -> Result<()> { +- let compilers = self.args.compiler.as_slice(); +- let binary_dir = self.args.binary_dir.as_path(); +- let object_dir = self.args.object_dir.as_path(); +- let binaries = self.args.binary.as_slice(); +- let debuginfos = self.args.debuginfo.as_slice(); +- +- let temp_dir = self.build_root.build_dir.as_path(); +- let original_dir = self.build_root.original_dir.as_path(); +- let patched_dir = self.build_root.patched_dir.as_path(); +- + info!("=============================="); + info!("{}", CLI_ABOUT); + info!("=============================="); + trace!("{:#?}", self.args); + +- info!("Checking compiler(s)"); +- self.compiler_map = CompilerInfo::parse(compilers, temp_dir)?; +- ++ info!("Detecting compiler(s)"); + info!("------------------------------"); + info!("Compiler"); + info!("------------------------------"); +- for (producer_type, compiler_info) in &self.compiler_map { +- info!( +- "[{}] compiler: {}, assembler: {}, linker: {}", +- producer_type, +- compiler_info.binary.display(), +- compiler_info.assembler.display(), +- compiler_info.linker.display(), +- ); +- } ++ self.detect_compilers()?; + + let project = Project::new(&self.args, &self.build_root, &self.compiler_map)?; + info!("------------------------------"); +@@ -269,11 +320,12 @@ impl UpatchBuild { + info!("Testing patch file(s)"); + project.test_patches().context("Patch test failed")?; + +- info!("Checking debuginfo version(s)"); ++ info!("Checking compiler version(s)"); + if self.args.skip_compiler_check { + warn!("Warning: Skipped compiler version check!") + } else { +- self.check_debuginfo().context("Debuginfo check failed")?; ++ self.check_compiler_version() ++ .context("Compiler version check failed")?; + } + + if !self.args.prepare_cmd.is_empty() { +@@ -297,6 +349,14 @@ impl UpatchBuild { + .context("Failed to override line macros")?; + } + ++ let binary_dir = self.args.binary_dir.as_path(); ++ let object_dir = self.args.object_dir.as_path(); ++ let binaries = self.args.binary.as_slice(); ++ let debuginfos = self.args.debuginfo.as_slice(); ++ ++ let original_dir = self.build_root.original_dir.as_path(); ++ let patched_dir = self.build_root.patched_dir.as_path(); ++ + info!("Building '{}'", project); + project + .build() +@@ -426,22 +486,6 @@ impl UpatchBuild { + + command.stdout(Level::Trace).run_with_output()?.exit_ok() + } +- +- fn link_objects(linker: P, objects: I, output: Q) -> Result<()> +- where +- P: AsRef, +- I: IntoIterator, +- S: AsRef, +- Q: AsRef, +- { +- Command::new(linker.as_ref()) +- .args(["-r", "-o"]) +- .arg(output.as_ref()) +- .args(objects) +- .stdout(Level::Trace) +- .run_with_output()? +- .exit_ok() +- } + } + + impl Drop for UpatchBuild { +diff --git a/upatch-build/src/project.rs b/upatch-build/src/project.rs +index d563c02..c05cd18 100644 +--- a/upatch-build/src/project.rs ++++ b/upatch-build/src/project.rs +@@ -26,7 +26,7 @@ use indexmap::IndexMap; + use log::{debug, Level}; + use which::which; + +-use crate::{args::Arguments, build_root::BuildRoot, compiler::CompilerInfo, dwarf::ProducerType}; ++use crate::{args::Arguments, build_root::BuildRoot, compiler::Compiler, dwarf::ProducerType}; + use syscare_common::{concat_os, ffi::OsStrExt, fs, process::Command}; + + const PATCH_BIN: &str = "patch"; +@@ -60,22 +60,25 @@ impl<'a> Project<'a> { + pub fn new( + args: &'a Arguments, + build_root: &'a BuildRoot, +- compiler_map: &'a IndexMap, ++ compiler_map: &'a IndexMap, + ) -> Result { + let path_env = env::var_os(PATH_ENV) + .with_context(|| format!("Cannot read environment variable '{}'", PATH_ENV))?; + let upatch_helper = which(UPATCH_HELPER_BIN) + .with_context(|| format!("Cannot find component '{}'", UPATCH_HELPER_BIN))?; + +- for (producer_type, compiler_info) in compiler_map { +- let compiler_bin = compiler_info.binary.as_path(); +- let compiler_name = compiler_bin ++ for (kind, compiler) in compiler_map { ++ let compiler_path = compiler.path.as_path(); ++ let compiler_name = compiler_path + .file_name() + .context("Failed to parse compiler name")?; +- +- match producer_type { +- ProducerType::C => env::set_var(UPATCH_CC_ENV, compiler_bin), +- ProducerType::Cxx => env::set_var(UPATCH_CXX_ENV, compiler_bin), ++ match kind { ++ ProducerType::GnuC | ProducerType::ClangC => { ++ env::set_var(UPATCH_CC_ENV, compiler_path) ++ } ++ ProducerType::GnuCxx | ProducerType::ClangCxx => { ++ env::set_var(UPATCH_CXX_ENV, compiler_path) ++ } + _ => {} + } + fs::soft_link(&upatch_helper, build_root.bin_dir.join(compiler_name))?; +-- +2.43.0 + diff --git a/0107-upatch-build-adapt-fs-glob-changes.patch b/0107-upatch-build-adapt-fs-glob-changes.patch new file mode 100644 index 0000000000000000000000000000000000000000..3e05821a81bb2dd5e8b558b1804e11b89cfc59bc --- /dev/null +++ b/0107-upatch-build-adapt-fs-glob-changes.patch @@ -0,0 +1,78 @@ +From e7f21ead8370e9ee99437779f0dd79d8a312119a Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 21 Apr 2025 10:36:11 +0800 +Subject: [PATCH] upatch-build: adapt fs::glob() changes + +Signed-off-by: renoseven +--- + upatch-build/src/file_relation.rs | 33 ++++++++++++++++++++----------- + 1 file changed, 21 insertions(+), 12 deletions(-) + +diff --git a/upatch-build/src/file_relation.rs b/upatch-build/src/file_relation.rs +index 2571873..c6ab75d 100644 +--- a/upatch-build/src/file_relation.rs ++++ b/upatch-build/src/file_relation.rs +@@ -26,7 +26,6 @@ use syscare_common::{concat_os, ffi::OsStrExt, fs}; + + use crate::elf; + +-const BUILD_ROOT_PREFIX: &str = "upatch-build."; + const UPATCH_ID_PREFIX: &str = ".upatch_"; + + const NON_EXIST_PATH: &str = "/dev/null"; +@@ -205,31 +204,41 @@ impl FileRelation { + } + + fn collect_objects( +- search_dir: P, ++ object_dir: P, + target_dir: Q, + ) -> Result> + where + P: AsRef, + Q: AsRef, + { +- let mut object_files = IndexSet::new(); ++ let object_dir = object_dir.as_ref(); ++ let target_dir = target_dir.as_ref(); + +- let matched_dirs = fs::glob(&search_dir) +- .with_context(|| format!("Cannot match path {}", search_dir.as_ref().display()))?; +- for matched_dir in matched_dirs { +- object_files.extend(elf::find_elf_files(&matched_dir, |obj_path, obj_kind| { +- !obj_path.contains(BUILD_ROOT_PREFIX) && (obj_kind == ObjectKind::Relocatable) +- })?); ++ let mut object_files = IndexSet::new(); ++ for match_result in fs::glob(object_dir) { ++ let matched_dir = match_result.with_context(|| { ++ format!("Cannot match object directory {}", object_dir.display()) ++ })?; ++ let found_files = ++ fs::list_files(&matched_dir, fs::TraverseOptions { recursive: true })? ++ .into_iter() ++ .filter(|file_path| { ++ matches!( ++ elf::parse_file_kind(file_path).unwrap_or(ObjectKind::Unknown), ++ ObjectKind::Relocatable ++ ) ++ }); ++ object_files.extend(found_files); + } + ensure!( + !object_files.is_empty(), +- "Cannot find any valid objects in {}, please add compile flag '-save-temps' manually", +- search_dir.as_ref().display() ++ "Cannot find any object in {}", ++ object_dir.display() + ); + + let mut object_relations = Vec::with_capacity(object_files.len()); + for (file_id, object_file) in object_files.into_iter().enumerate() { +- let object_archive = target_dir.as_ref().join(concat_os!( ++ let object_archive = target_dir.join(concat_os!( + format!("{:04}-", file_id), + object_file.file_name().with_context(|| { + format!("Failed to parse file name of {}", object_file.display()) +-- +2.43.0 + diff --git a/0108-upatch-build-binary-dir-supports-wildcard-path.patch b/0108-upatch-build-binary-dir-supports-wildcard-path.patch new file mode 100644 index 0000000000000000000000000000000000000000..cc2c5e3dcc93ebffdedfe4e401fdd65543600841 --- /dev/null +++ b/0108-upatch-build-binary-dir-supports-wildcard-path.patch @@ -0,0 +1,73 @@ +From b98c6423abb6018b93fce727d147915ae84d3b8d Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 21 Apr 2025 11:49:37 +0800 +Subject: [PATCH] upatch-build: '--binary-dir' supports wildcard path + +Signed-off-by: renoseven +--- + upatch-build/src/file_relation.rs | 43 +++++++++++++++++-------------- + 1 file changed, 24 insertions(+), 19 deletions(-) + +diff --git a/upatch-build/src/file_relation.rs b/upatch-build/src/file_relation.rs +index c6ab75d..6aa6111 100644 +--- a/upatch-build/src/file_relation.rs ++++ b/upatch-build/src/file_relation.rs +@@ -75,31 +75,36 @@ impl FileRelation { + let mut debuginfo_iter = debuginfos.into_iter(); + + while let (Some(binary), Some(debuginfo)) = (binary_iter.next(), debuginfo_iter.next()) { +- let binary_path = binary_dir.as_ref().join(&binary); +- let binary_files = +- fs::list_files(&binary_dir, fs::TraverseOptions { recursive: true })? +- .into_iter() +- .filter(|file_path| { +- file_path.ends_with(binary.as_ref().as_os_str()) +- && matches!( ++ let binary_dir = binary_dir.as_ref(); ++ let binary_path = binary.as_ref().as_os_str(); ++ ++ let mut binary_files = IndexSet::new(); ++ for match_result in fs::glob(binary_dir) { ++ let matched_dir = match_result.with_context(|| { ++ format!("Cannot match binary directory {}", binary_dir.display()) ++ })?; ++ let found_files = ++ fs::list_files(matched_dir, fs::TraverseOptions { recursive: true })? ++ .into_iter() ++ .filter(|file_path| file_path.ends_with(binary_path)) ++ .filter(|file_path| { ++ matches!( + elf::parse_file_kind(file_path).unwrap_or(ObjectKind::Unknown), + ObjectKind::Executable | ObjectKind::Dynamic + ) +- }) +- .collect::>(); +- +- ensure!( +- !binary_files.is_empty(), +- "Path {} does not match to any file", +- binary_path.display() +- ); ++ }); ++ binary_files.extend(found_files); ++ } ++ let binary_file = binary_files ++ .pop() ++ .with_context(|| format!("Cannot find any binary in {}", binary_dir.display()))?; + ensure!( +- binary_files.len() == 1, +- "Path {} matches to too many file", +- binary_path.display() ++ binary_files.is_empty(), ++ "Binary {} matched to too many files", ++ binary_path.to_string_lossy() + ); + self.binary_debuginfo_map +- .insert(binary_files[0].clone(), debuginfo.as_ref().to_path_buf()); ++ .insert(binary_file, debuginfo.as_ref().to_path_buf()); + } + + Ok(()) +-- +2.43.0 + diff --git a/0109-upatch-build-adapt-common-fs-changes.patch b/0109-upatch-build-adapt-common-fs-changes.patch new file mode 100644 index 0000000000000000000000000000000000000000..b33490c3f9b4c9f5926437d113e4100fd05b7567 --- /dev/null +++ b/0109-upatch-build-adapt-common-fs-changes.patch @@ -0,0 +1,171 @@ +From 996090a92a147bde7d7b652ae3b5c3bcef496147 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 21 Apr 2025 20:02:38 +0800 +Subject: [PATCH] upatch-build: adapt common::fs changes + +Signed-off-by: renoseven +--- + upatch-build/src/dwarf.rs | 19 ++++++++----------- + upatch-build/src/elf/elfs.rs | 16 +++++++++++++--- + upatch-build/src/file_relation.rs | 7 ++----- + upatch-build/src/main.rs | 29 +++++++++++++---------------- + 4 files changed, 36 insertions(+), 35 deletions(-) + +diff --git a/upatch-build/src/dwarf.rs b/upatch-build/src/dwarf.rs +index c93cfa9..4934a7a 100644 +--- a/upatch-build/src/dwarf.rs ++++ b/upatch-build/src/dwarf.rs +@@ -12,11 +12,12 @@ use gimli::{ + constants::*, AttributeValue, DebugInfoUnitHeadersIter, DebuggingInformationEntry, DwLang, + Dwarf, EndianRcSlice, Endianity, Reader, RunTimeEndian, SectionId, Unit, UnitOffset, + }; +-use memmap2::Mmap; + use object::{Endianness, Object, ObjectSection, ObjectSymbol, RelocationKind, RelocationTarget}; + use once_cell::sync::Lazy; + use regex::bytes::Regex; + ++use syscare_common::fs::{self, FileMmap}; ++ + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub enum ProducerType { + GnuAs, +@@ -67,22 +68,18 @@ impl std::fmt::Display for Producer { + } + + pub struct ProducerParser { +- _file: std::fs::File, +- mmap: Mmap, ++ mmap: FileMmap, + data_map: RefCell>>, + } + + impl ProducerParser { + pub fn open>(path: P) -> Result { +- let _file = std::fs::File::open(path)?; +- let mmap = unsafe { Mmap::map(&_file)? }; +- mmap.advise(memmap2::Advice::Random)?; +- +- Ok(Self { +- _file, +- mmap, ++ let parser = Self { ++ mmap: fs::mmap(&path) ++ .with_context(|| format!("Failed to mmap file {}", path.as_ref().display()))?, + data_map: RefCell::new(HashMap::new()), +- }) ++ }; ++ Ok(parser) + } + + pub fn parse(&self) -> Result + '_>> { +diff --git a/upatch-build/src/elf/elfs.rs b/upatch-build/src/elf/elfs.rs +index 25e462d..d6548a9 100644 +--- a/upatch-build/src/elf/elfs.rs ++++ b/upatch-build/src/elf/elfs.rs +@@ -25,8 +25,18 @@ use syscare_common::fs; + + use super::{Endian, Endianness}; + +-pub fn parse_file_kind>(file_path: P) -> Result { +- Ok(object::File::parse(fs::MappedFile::open(&file_path)?.as_bytes())?.kind()) ++fn parse_elf_kind>(file_path: P) -> Result { ++ let path = file_path.as_ref(); ++ let mmap = ++ fs::mmap(path).with_context(|| format!("Failed to mmap file {}", path.display()))?; ++ let file = object::File::parse(mmap.as_ref()) ++ .with_context(|| format!("Failed to parse {}", path.display()))?; ++ ++ Ok(file.kind()) ++} ++ ++pub fn elf_kind>(file_path: P) -> ObjectKind { ++ self::parse_elf_kind(file_path).unwrap_or(ObjectKind::Unknown) + } + + pub fn find_elf_files(directory: P, predicate: F) -> Result> +@@ -36,7 +46,7 @@ where + { + let mut elf_files = Vec::new(); + for file_path in fs::list_files(&directory, fs::TraverseOptions { recursive: true })? { +- if let Ok(obj_kind) = self::parse_file_kind(&file_path) { ++ if let Ok(obj_kind) = self::parse_elf_kind(&file_path) { + if predicate(&file_path, obj_kind) { + elf_files.push(file_path); + } +diff --git a/upatch-build/src/file_relation.rs b/upatch-build/src/file_relation.rs +index 6aa6111..0ac03ca 100644 +--- a/upatch-build/src/file_relation.rs ++++ b/upatch-build/src/file_relation.rs +@@ -89,7 +89,7 @@ impl FileRelation { + .filter(|file_path| file_path.ends_with(binary_path)) + .filter(|file_path| { + matches!( +- elf::parse_file_kind(file_path).unwrap_or(ObjectKind::Unknown), ++ elf::elf_kind(file_path), + ObjectKind::Executable | ObjectKind::Dynamic + ) + }); +@@ -228,10 +228,7 @@ impl FileRelation { + fs::list_files(&matched_dir, fs::TraverseOptions { recursive: true })? + .into_iter() + .filter(|file_path| { +- matches!( +- elf::parse_file_kind(file_path).unwrap_or(ObjectKind::Unknown), +- ObjectKind::Relocatable +- ) ++ matches!(elf::elf_kind(file_path), ObjectKind::Relocatable) + }); + object_files.extend(found_files); + } +diff --git a/upatch-build/src/main.rs b/upatch-build/src/main.rs +index 56a8715..c791795 100644 +--- a/upatch-build/src/main.rs ++++ b/upatch-build/src/main.rs +@@ -29,12 +29,7 @@ use indexmap::{IndexMap, IndexSet}; + use log::{debug, error, info, trace, warn, Level, LevelFilter, Record}; + use object::{write, Object, ObjectKind, ObjectSection, SectionKind}; + +-use syscare_common::{ +- concat_os, +- fs::{self, MappedFile}, +- os, +- process::Command, +-}; ++use syscare_common::{concat_os, fs, os, process::Command}; + + mod args; + mod build_root; +@@ -425,18 +420,20 @@ impl UpatchBuild { + write!(w, "{}", record.args()) + } + +- fn create_note, Q: AsRef>(debuginfo: P, output_file: Q) -> Result<()> { +- let debuginfo_file = MappedFile::open(&debuginfo)?; +- let object_file = object::File::parse(debuginfo_file.as_bytes()) +- .with_context(|| format!("Failed to parse {}", debuginfo.as_ref().display()))?; ++ fn create_note, Q: AsRef>( ++ debuginfo_file: P, ++ output_file: Q, ++ ) -> Result<()> { ++ let debuginfo_file = debuginfo_file.as_ref(); ++ let mmap = fs::mmap(debuginfo_file) ++ .with_context(|| format!("Failed to mmap file {}", debuginfo_file.display()))?; ++ let file = object::File::parse(mmap.as_ref()) ++ .with_context(|| format!("Failed to parse {}", debuginfo_file.display()))?; + +- let mut new_object = write::Object::new( +- object_file.format(), +- object_file.architecture(), +- object_file.endianness(), +- ); ++ let mut new_object = ++ write::Object::new(file.format(), file.architecture(), file.endianness()); + +- for section in object_file.sections() { ++ for section in file.sections() { + if section.kind() != SectionKind::Note { + continue; + } +-- +2.43.0 + diff --git a/0110-upatch-build-format-code.patch b/0110-upatch-build-format-code.patch new file mode 100644 index 0000000000000000000000000000000000000000..b16194952a85e093997015dd8d87a4e6b39e791d --- /dev/null +++ b/0110-upatch-build-format-code.patch @@ -0,0 +1,27 @@ +From c69ae01bb53458dd7fdfda0d0b3c5dba385f6539 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Tue, 22 Apr 2025 16:53:41 +0800 +Subject: [PATCH] upatch-build: format code + +Signed-off-by: renoseven +--- + upatch-build/src/elf/elfs.rs | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/upatch-build/src/elf/elfs.rs b/upatch-build/src/elf/elfs.rs +index d6548a9..8d9abb1 100644 +--- a/upatch-build/src/elf/elfs.rs ++++ b/upatch-build/src/elf/elfs.rs +@@ -27,8 +27,7 @@ use super::{Endian, Endianness}; + + fn parse_elf_kind>(file_path: P) -> Result { + let path = file_path.as_ref(); +- let mmap = +- fs::mmap(path).with_context(|| format!("Failed to mmap file {}", path.display()))?; ++ let mmap = fs::mmap(path).with_context(|| format!("Failed to mmap file {}", path.display()))?; + let file = object::File::parse(mmap.as_ref()) + .with_context(|| format!("Failed to parse {}", path.display()))?; + +-- +2.43.0 + diff --git a/0111-upatch-build-fix-upatch-id-parsing-failure.patch b/0111-upatch-build-fix-upatch-id-parsing-failure.patch new file mode 100644 index 0000000000000000000000000000000000000000..604ee90a2efe50443343dd49484235d306e04fa5 --- /dev/null +++ b/0111-upatch-build-fix-upatch-id-parsing-failure.patch @@ -0,0 +1,47 @@ +From d4db3bae1888725a24d308c2af0fe195f8f1249f Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Tue, 22 Apr 2025 16:02:36 +0800 +Subject: [PATCH] upatch-build: fix upatch id parsing failure + +1. fix upatch id parsing failure when some object + does not have '.symtab' section + +Signed-off-by: renoseven +--- + upatch-build/src/file_relation.rs | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/upatch-build/src/file_relation.rs b/upatch-build/src/file_relation.rs +index 0ac03ca..81cd974 100644 +--- a/upatch-build/src/file_relation.rs ++++ b/upatch-build/src/file_relation.rs +@@ -173,15 +173,20 @@ impl FileRelation { + impl FileRelation { + fn parse_upatch_ids>(file_path: P) -> Result> { + let file_path = file_path.as_ref(); +- let elf_file = elf::read::Elf::parse(file_path).context("Failed to parse elf")?; +- let symbols = elf_file.symbols().context("Failed to read elf symbols")?; ++ let mmap = fs::mmap(file_path) ++ .with_context(|| format!("Failed to mmap {}", file_path.display()))?; ++ let file = object::File::parse(mmap.as_ref()) ++ .with_context(|| format!("Failed to parse {}", file_path.display()))?; + + let mut upatch_ids = IndexSet::new(); +- for symbol in symbols { +- let symbol_name = symbol.get_st_name(); +- if symbol_name.starts_with(UPATCH_ID_PREFIX) { +- upatch_ids.insert(symbol_name.to_os_string()); ++ for symbol in file.symbols() { ++ let name_slice = symbol.name_bytes().with_context(|| { ++ format!("Failed to parse symbol name, index={}", symbol.index().0) ++ })?; ++ if !name_slice.starts_with(UPATCH_ID_PREFIX.as_bytes()) { ++ continue; + } ++ upatch_ids.insert(OsStr::from_bytes(name_slice).to_os_string()); + } + + Ok(upatch_ids) +-- +2.43.0 + diff --git a/0112-upatch-build-rename-patch-note-object.patch b/0112-upatch-build-rename-patch-note-object.patch new file mode 100644 index 0000000000000000000000000000000000000000..b2f628b26d4b59ace18bace84da980133f302e61 --- /dev/null +++ b/0112-upatch-build-rename-patch-note-object.patch @@ -0,0 +1,29 @@ +From b4885afe364e28888d4e6e25b519b4f3760d6886 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Tue, 22 Apr 2025 17:42:17 +0800 +Subject: [PATCH] upatch-build: rename patch note object + +1. added patch name before note object name + e.g. notes.o -> xxxx-notes.o + +Signed-off-by: renoseven +--- + upatch-build/src/main.rs | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/upatch-build/src/main.rs b/upatch-build/src/main.rs +index c791795..bb71793 100644 +--- a/upatch-build/src/main.rs ++++ b/upatch-build/src/main.rs +@@ -259,7 +259,7 @@ impl UpatchBuild { + } + + debug!("- Creating patch notes"); +- let notes_object = temp_dir.join(NOTES_OBJECT_NAME); ++ let notes_object = temp_dir.join(concat_os!(patch_name, "-", NOTES_OBJECT_NAME)); + Self::create_note(&debuginfo_file, ¬es_object) + .context("Failed to create patch notes")?; + objects.push(notes_object); +-- +2.43.0 + diff --git a/0113-upatch-build-rewrite-object-collecting.patch b/0113-upatch-build-rewrite-object-collecting.patch new file mode 100644 index 0000000000000000000000000000000000000000..b5efb975e94669b132ce0b81b1544cc26e2c39b8 --- /dev/null +++ b/0113-upatch-build-rewrite-object-collecting.patch @@ -0,0 +1,171 @@ +From 72b7c9bcd51f2779c4c5d060ac7b61d4c35e5228 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Tue, 22 Apr 2025 15:25:35 +0800 +Subject: [PATCH] upatch-build: rewrite object collecting + +1. parsing object type & upatch id while collecting, + so that we don't need access object file many times +2. optimize upatch id to object path mapping + +Signed-off-by: renoseven +--- + upatch-build/src/file_relation.rs | 116 +++++++++++++++++++----------- + 1 file changed, 73 insertions(+), 43 deletions(-) + +diff --git a/upatch-build/src/file_relation.rs b/upatch-build/src/file_relation.rs +index 81cd974..15aeb33 100644 +--- a/upatch-build/src/file_relation.rs ++++ b/upatch-build/src/file_relation.rs +@@ -13,7 +13,8 @@ + */ + + use std::{ +- ffi::OsString, ++ ffi::{OsStr, OsString}, ++ os::unix::ffi::OsStrExt, + path::{Path, PathBuf}, + }; + +@@ -21,8 +22,9 @@ use anyhow::{ensure, Context, Result}; + + use indexmap::{IndexMap, IndexSet}; + use log::warn; +-use object::ObjectKind; +-use syscare_common::{concat_os, ffi::OsStrExt, fs}; ++use object::{Object, ObjectKind, ObjectSymbol}; ++ ++use syscare_common::{concat_os, ffi::OsStrExt as _, fs}; + + use crate::elf; + +@@ -224,59 +226,87 @@ impl FileRelation { + let object_dir = object_dir.as_ref(); + let target_dir = target_dir.as_ref(); + +- let mut object_files = IndexSet::new(); ++ let mut file_id = 1usize; ++ let mut object_info = Vec::new(); + for match_result in fs::glob(object_dir) { + let matched_dir = match_result.with_context(|| { + format!("Cannot match object directory {}", object_dir.display()) + })?; +- let found_files = +- fs::list_files(&matched_dir, fs::TraverseOptions { recursive: true })? +- .into_iter() +- .filter(|file_path| { +- matches!(elf::elf_kind(file_path), ObjectKind::Relocatable) +- }); +- object_files.extend(found_files); ++ ++ let file_list = fs::list_files(&matched_dir, fs::TraverseOptions { recursive: true })?; ++ for object_file in file_list { ++ let mmap = fs::mmap(&object_file) ++ .with_context(|| format!("Failed to mmap {}", object_file.display()))?; ++ ++ // Try to parse file as elf ++ let file = match object::File::parse(mmap.as_ref()) { ++ Ok(f) => f, ++ Err(_) => continue, ++ }; ++ ++ // We only care about object file ++ if !matches!(file.kind(), ObjectKind::Relocatable) { ++ continue; ++ } ++ ++ // Copy object file to target directory ++ let obj_name = object_file.file_name().unwrap_or_default(); ++ let archive_file = ++ target_dir.join(concat_os!(format!("{:04}-", file_id), obj_name)); ++ fs::copy(&object_file, &archive_file)?; ++ file_id += 1; ++ ++ // Parse upatch id of the object ++ let upatch_ids = file ++ .symbols() ++ .filter_map(|symbol| { ++ let sym_name = symbol.name_bytes().unwrap_or_default(); ++ if !sym_name.starts_with(UPATCH_ID_PREFIX.as_bytes()) { ++ return None; ++ } ++ Some(OsStr::from_bytes(sym_name).to_os_string()) ++ }) ++ .collect::>(); ++ if upatch_ids.is_empty() { ++ warn!( ++ "Object {} does not contain upatch id", ++ object_file.display() ++ ); ++ continue; ++ } ++ ++ object_info.push((object_file, archive_file, upatch_ids)); ++ } + } + ensure!( +- !object_files.is_empty(), ++ !object_info.is_empty(), + "Cannot find any object in {}", + object_dir.display() + ); + +- let mut object_relations = Vec::with_capacity(object_files.len()); +- for (file_id, object_file) in object_files.into_iter().enumerate() { +- let object_archive = target_dir.join(concat_os!( +- format!("{:04}-", file_id), +- object_file.file_name().with_context(|| { +- format!("Failed to parse file name of {}", object_file.display()) +- })? +- )); +- fs::copy(&object_file, &object_archive)?; +- +- let upatch_ids = Self::parse_upatch_ids(&object_file).with_context(|| { +- format!("Failed to parse upatch id of {}", object_file.display()) +- })?; +- object_relations.push((object_file, object_archive, upatch_ids)); +- } ++ // We want subsequent objects to contain more identifiers. ++ object_info.sort_by(|(_, _, lhs), (_, _, rhs)| lhs.len().cmp(&rhs.len())); + +- let mut id_object_map = IndexMap::with_capacity(object_relations.len()); +- for (object_file, object_archive, object_ids) in &object_relations { +- if object_relations.iter().all(|(obj, _, ids)| { +- if (obj != object_file) && !ids.is_empty() && ids.is_subset(object_ids) { +- warn!("Skipped object {}", object_archive.display()); +- return false; +- } +- true +- }) { +- id_object_map.extend(object_ids.iter().map(|id| { +- ( +- id.to_os_string(), +- (object_file.clone(), object_archive.clone()), +- ) +- })); ++ let mut upatch_id_map = IndexMap::new(); ++ while let Some((object_file, archive_file, mut upatch_ids)) = object_info.pop() { ++ // Remove identifiers in other objects ++ for (_, _, ids) in &object_info { ++ upatch_ids.retain(|id| !ids.contains(id)); ++ } ++ // Current object is fully composed of other objects, we skip it. ++ if upatch_ids.is_empty() { ++ warn!("Skipped {}", object_file.display()); ++ } ++ for upatch_id in upatch_ids { ++ upatch_id_map.insert(upatch_id, (object_file.clone(), archive_file.clone())); + } + } ++ ensure!( ++ !upatch_id_map.is_empty(), ++ "Cannot find any upatch id in {}", ++ object_dir.display() ++ ); + +- Ok(id_object_map) ++ Ok(upatch_id_map) + } + } +-- +2.43.0 + diff --git a/0114-upatch-build-fix-unable-to-find-object-linker-error.patch b/0114-upatch-build-fix-unable-to-find-object-linker-error.patch new file mode 100644 index 0000000000000000000000000000000000000000..88096896172a9977b43fbd225b70fbc535301075 --- /dev/null +++ b/0114-upatch-build-fix-unable-to-find-object-linker-error.patch @@ -0,0 +1,76 @@ +From 448679c40d56fec8e8c53e1d41dcfb9b44077233 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 8 May 2025 16:14:44 +0800 +Subject: [PATCH] upatch-build: fix unable to find object linker error + +Signed-off-by: renoseven +--- + upatch-build/src/main.rs | 39 ++++++++++++++------------------------- + 1 file changed, 14 insertions(+), 25 deletions(-) + +diff --git a/upatch-build/src/main.rs b/upatch-build/src/main.rs +index bb71793..b23d3b2 100644 +--- a/upatch-build/src/main.rs ++++ b/upatch-build/src/main.rs +@@ -167,36 +167,25 @@ impl UpatchBuild { + Ok(()) + } + +- fn find_linker(&self, objects: &[PathBuf]) -> Result<&Path> { +- let mut producers = IndexSet::new(); +- for path in objects { +- let producer_parser = ProducerParser::open(path) +- .with_context(|| format!("Failed to open {}", path.display()))?; +- let producer_iter = producer_parser +- .parse() +- .with_context(|| format!("Failed to parse {}", path.display()))?; +- +- for parse_result in producer_iter { +- let producer = parse_result.context("Failed to parse object producer")?; +- if producer.is_assembler() { +- continue; +- } +- producers.insert(producer); +- } +- } ++ fn find_linker(&self, debuginfo: &Path) -> Result<&Path> { ++ let mut producers = ProducerParser::open(debuginfo) ++ .with_context(|| format!("Failed to open {}", debuginfo.display()))? ++ .parse() ++ .with_context(|| format!("Failed to parse {}", debuginfo.display()))? ++ .filter_map(|result| result.ok()) ++ .collect::>(); + producers.sort(); + +- let producer = producers.pop().context("No object producer")?; +- let compiler = self +- .compiler_map +- .get(&producer.kind) +- .with_context(|| format!("Cannot find {} compiler", producer.kind))?; ++ let compiler = producers ++ .pop() ++ .and_then(|producer| self.compiler_map.get(&producer.kind)) ++ .context("Cannot find linking compiler")?; + + Ok(compiler.linker.as_path()) + } + +- fn link_objects(&self, objects: &[PathBuf], output: &Path) -> Result<()> { +- let linker = self.find_linker(objects).context("Cannot find linker")?; ++ fn link_objects(&self, objects: &[PathBuf], debuginfo: &Path, output: &Path) -> Result<()> { ++ let linker = self.find_linker(debuginfo).context("Cannot find linker")?; + + Command::new(linker) + .args(["-r", "-o"]) +@@ -265,7 +254,7 @@ impl UpatchBuild { + objects.push(notes_object); + + debug!("- Linking patch"); +- self.link_objects(&objects, &output_file) ++ self.link_objects(&objects, &debuginfo_file, &output_file) + .context("Failed to link patch objects")?; + + debug!("- Resolving patch"); +-- +2.43.0 + diff --git a/0115-upatch-build-warning-on-finding-patched-object-failu.patch b/0115-upatch-build-warning-on-finding-patched-object-failu.patch new file mode 100644 index 0000000000000000000000000000000000000000..4b033bb9144b7383b8597779b7b719685abd0a14 --- /dev/null +++ b/0115-upatch-build-warning-on-finding-patched-object-failu.patch @@ -0,0 +1,56 @@ +From f5c4b148e5288ca3dbc779331e6184a9ba436661 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 8 May 2025 11:14:30 +0800 +Subject: [PATCH] upatch-build: warning on finding patched object failure + +Signed-off-by: renoseven +--- + upatch-build/src/file_relation.rs | 32 +++++++++++++++++-------------- + 1 file changed, 18 insertions(+), 14 deletions(-) + +diff --git a/upatch-build/src/file_relation.rs b/upatch-build/src/file_relation.rs +index 15aeb33..c33983d 100644 +--- a/upatch-build/src/file_relation.rs ++++ b/upatch-build/src/file_relation.rs +@@ -137,20 +137,24 @@ impl FileRelation { + let mut object_relation = IndexMap::new(); + + for upatch_id in upatch_ids { +- let (object_file, patched_object) = +- id_object_map.get(&upatch_id).with_context(|| { +- format!( +- "Cannot find patched object of {}", +- upatch_id.to_string_lossy() +- ) +- })?; +- let original_object = self +- .original_object_map +- .get(object_file) +- .map(|p| p.as_path()) +- .unwrap_or_else(|| Path::new(NON_EXIST_PATH)); +- +- object_relation.insert(patched_object.to_path_buf(), original_object.to_path_buf()); ++ match id_object_map.get(&upatch_id) { ++ Some((object_file, patched_object)) => { ++ let original_object = self ++ .original_object_map ++ .get(object_file) ++ .map(|p| p.as_path()) ++ .unwrap_or_else(|| Path::new(NON_EXIST_PATH)); ++ object_relation ++ .insert(patched_object.to_path_buf(), original_object.to_path_buf()); ++ } ++ None => { ++ warn!( ++ "Cannot find patched object of {} in target {}", ++ upatch_id.to_string_lossy(), ++ binary_file.display() ++ ); ++ } ++ } + } + object_relation.sort_keys(); + +-- +2.43.0 + diff --git a/0116-upatch-build-try-hardlink-before-copy-files.patch b/0116-upatch-build-try-hardlink-before-copy-files.patch new file mode 100644 index 0000000000000000000000000000000000000000..2944db325949734720a7690496ee15ecff396bc6 --- /dev/null +++ b/0116-upatch-build-try-hardlink-before-copy-files.patch @@ -0,0 +1,44 @@ +From c3b6011bd6a43c32281f43c11b0a14ae056ff535 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 8 May 2025 12:48:20 +0800 +Subject: [PATCH] upatch-build: try hardlink before copy files + +Signed-off-by: renoseven +--- + upatch-build/src/file_relation.rs | 4 +++- + upatch-build/src/main.rs | 4 +++- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/upatch-build/src/file_relation.rs b/upatch-build/src/file_relation.rs +index c33983d..3c71e50 100644 +--- a/upatch-build/src/file_relation.rs ++++ b/upatch-build/src/file_relation.rs +@@ -257,7 +257,9 @@ impl FileRelation { + let obj_name = object_file.file_name().unwrap_or_default(); + let archive_file = + target_dir.join(concat_os!(format!("{:04}-", file_id), obj_name)); +- fs::copy(&object_file, &archive_file)?; ++ if fs::hard_link(&object_file, &archive_file).is_err() { ++ fs::copy(&object_file, &archive_file)?; ++ } + file_id += 1; + + // Parse upatch id of the object +diff --git a/upatch-build/src/main.rs b/upatch-build/src/main.rs +index b23d3b2..45be298 100644 +--- a/upatch-build/src/main.rs ++++ b/upatch-build/src/main.rs +@@ -210,7 +210,9 @@ impl UpatchBuild { + let output_file = output_dir.join(patch_name); + + fs::create_dir_all(&temp_dir)?; +- fs::copy(debuginfo, &debuginfo_file)?; ++ if fs::hard_link(debuginfo, &debuginfo_file).is_err() { ++ fs::copy(debuginfo, &debuginfo_file)?; ++ } + fs::set_permissions(&debuginfo_file, Permissions::from_mode(0o644))?; + + debug!("- Resolving debuginfo"); +-- +2.43.0 + diff --git a/0117-upatch-build-optimize-code.patch b/0117-upatch-build-optimize-code.patch new file mode 100644 index 0000000000000000000000000000000000000000..b4b4b71d417044b84f9b3c15c0eecf7cf39cf6b2 --- /dev/null +++ b/0117-upatch-build-optimize-code.patch @@ -0,0 +1,88 @@ +From fb4201b9ffeefb785266a1f097efbb142959d4df Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 8 May 2025 16:19:46 +0800 +Subject: [PATCH] upatch-build: optimize code + +1. remove fn format_log() +2. change fn create_note() param types + +Signed-off-by: renoseven +--- + upatch-build/src/main.rs | 31 ++++++++----------------------- + 1 file changed, 8 insertions(+), 23 deletions(-) + +diff --git a/upatch-build/src/main.rs b/upatch-build/src/main.rs +index 45be298..6b48b78 100644 +--- a/upatch-build/src/main.rs ++++ b/upatch-build/src/main.rs +@@ -22,11 +22,9 @@ use std::{ + }; + + use anyhow::{bail, ensure, Context, Result}; +-use flexi_logger::{ +- DeferredNow, Duplicate, FileSpec, LogSpecification, Logger, LoggerHandle, WriteMode, +-}; ++use flexi_logger::{Duplicate, FileSpec, LogSpecification, Logger, LoggerHandle, WriteMode}; + use indexmap::{IndexMap, IndexSet}; +-use log::{debug, error, info, trace, warn, Level, LevelFilter, Record}; ++use log::{debug, error, info, trace, warn, Level, LevelFilter}; + use object::{write, Object, ObjectKind, ObjectSection, SectionKind}; + + use syscare_common::{concat_os, fs, os, process::Command}; +@@ -98,7 +96,7 @@ impl UpatchBuild { + let logger = Logger::with(log_spec) + .log_to_file(file_spec) + .duplicate_to_stdout(Duplicate::from(log_level_stdout)) +- .format(Self::format_log) ++ .format(|w, _, record| write!(w, "{}", record.args())) + .write_mode(WriteMode::Direct) + .start() + .context("Failed to initialize logger")?; +@@ -403,23 +401,11 @@ impl UpatchBuild { + + /* Tool functions */ + impl UpatchBuild { +- fn format_log( +- w: &mut dyn std::io::Write, +- _now: &mut DeferredNow, +- record: &Record, +- ) -> std::io::Result<()> { +- write!(w, "{}", record.args()) +- } +- +- fn create_note, Q: AsRef>( +- debuginfo_file: P, +- output_file: Q, +- ) -> Result<()> { +- let debuginfo_file = debuginfo_file.as_ref(); +- let mmap = fs::mmap(debuginfo_file) +- .with_context(|| format!("Failed to mmap file {}", debuginfo_file.display()))?; ++ fn create_note(debuginfo: &Path, output: &Path) -> Result<()> { ++ let mmap = fs::mmap(debuginfo) ++ .with_context(|| format!("Failed to mmap file {}", debuginfo.display()))?; + let file = object::File::parse(mmap.as_ref()) +- .with_context(|| format!("Failed to parse {}", debuginfo_file.display()))?; ++ .with_context(|| format!("Failed to parse {}", debuginfo.display()))?; + + let mut new_object = + write::Object::new(file.format(), file.architecture(), file.endianness()); +@@ -428,7 +414,6 @@ impl UpatchBuild { + if section.kind() != SectionKind::Note { + continue; + } +- + let section_name = section.name().context("Failed to get section name")?; + let section_data = section.data().context("Failed to get section data")?; + let section_id = +@@ -442,7 +427,7 @@ impl UpatchBuild { + let contents = new_object + .write() + .context("Failed to serialize note object")?; +- fs::write(output_file, contents)?; ++ fs::write(output, contents)?; + + Ok(()) + } +-- +2.43.0 + diff --git a/0118-upatch-build-support-text-section-offset.patch b/0118-upatch-build-support-text-section-offset.patch new file mode 100644 index 0000000000000000000000000000000000000000..1350de99c91bf96b0486c42540213ac0e199b1e1 --- /dev/null +++ b/0118-upatch-build-support-text-section-offset.patch @@ -0,0 +1,101 @@ +From ea5db116bc4e72ad8ff91afc88d6f7b9abcd5d92 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 12 May 2025 11:23:52 +0800 +Subject: [PATCH] upatch-build: support text section offset + +Signed-off-by: renoseven +--- + upatch-build/src/main.rs | 49 ++++++++++++++++++++++++++++++++-------- + 1 file changed, 39 insertions(+), 10 deletions(-) + +diff --git a/upatch-build/src/main.rs b/upatch-build/src/main.rs +index 6b48b78..29d68f6 100644 +--- a/upatch-build/src/main.rs ++++ b/upatch-build/src/main.rs +@@ -194,6 +194,23 @@ impl UpatchBuild { + .exit_ok() + } + ++ fn parse_text_offset(&self, binary: &Path) -> Result { ++ const TEXT_SECTION_NAME: &str = ".text"; ++ ++ let mmap = fs::mmap(binary)?; ++ let file = object::File::parse(mmap.as_ref())?; ++ let text_offset = file ++ .section_by_name(TEXT_SECTION_NAME) ++ .map(|section| { ++ let address = section.address(); ++ let offset = section.file_range().map(|(start, _)| start).unwrap_or(0); ++ address - offset ++ }) ++ .unwrap_or(0); ++ ++ Ok(text_offset) ++ } ++ + fn build_patch(&self, patch_name: &OsStr, binary: &Path, debuginfo: &Path) -> Result<()> { + const NOTES_OBJECT_NAME: &str = "notes.o"; + +@@ -222,6 +239,9 @@ impl UpatchBuild { + .binary_objects(binary) + .with_context(|| format!("Failed to find objects of {}", binary.display()))?; + ++ let text_offset = self ++ .parse_text_offset(binary) ++ .with_context(|| format!("Failed to parse {} text section offset", binary.display()))?; + for (patched_object, original_object) in binary_objects { + debug!( + "* {}", +@@ -230,13 +250,19 @@ impl UpatchBuild { + .unwrap_or(patched_object.as_os_str()) + .to_string_lossy() + ); +- Self::create_diff_objs(original_object, patched_object, &debuginfo_file, &temp_dir) +- .with_context(|| { +- format!( +- "Failed to create diff objects for {}", +- patch_name.to_string_lossy() +- ) +- })?; ++ Self::create_diff_objs( ++ original_object, ++ patched_object, ++ &debuginfo_file, ++ text_offset, ++ &temp_dir, ++ ) ++ .with_context(|| { ++ format!( ++ "Failed to create diff objects for {}", ++ patch_name.to_string_lossy() ++ ) ++ })?; + } + + debug!("- Collecting changes"); +@@ -436,6 +462,7 @@ impl UpatchBuild { + original_object: &Path, + patched_object: &Path, + debuginfo: &Path, ++ text_offset: u64, + output_dir: &Path, + ) -> Result<()> { + let ouput_name = original_object.file_name().with_context(|| { +@@ -453,9 +480,11 @@ impl UpatchBuild { + .arg("-p") + .arg(patched_object) + .arg("-r") +- .arg(debuginfo) +- .arg("-o") +- .arg(output_file); ++ .arg(debuginfo); ++ if text_offset > 0 { ++ command.arg("-t").arg(text_offset.to_string()); ++ } ++ command.arg("-o").arg(output_file); + + command.stdout(Level::Trace).run_with_output()?.exit_ok() + } +-- +2.43.0 + diff --git a/0119-syscare-build-fix-clippy-warnings.patch b/0119-syscare-build-fix-clippy-warnings.patch new file mode 100644 index 0000000000000000000000000000000000000000..7c018101d153230699611f78f7ffc242df41b0a5 --- /dev/null +++ b/0119-syscare-build-fix-clippy-warnings.patch @@ -0,0 +1,26 @@ +From d840052b40dc5fba5e73671b103412e6554a2e9f Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 8 May 2025 16:23:05 +0800 +Subject: [PATCH] syscare-build: fix clippy warnings + +Signed-off-by: renoseven +--- + syscare-build/src/package/rpm/spec_writer.rs | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/syscare-build/src/package/rpm/spec_writer.rs b/syscare-build/src/package/rpm/spec_writer.rs +index 97218c2..0059aee 100644 +--- a/syscare-build/src/package/rpm/spec_writer.rs ++++ b/syscare-build/src/package/rpm/spec_writer.rs +@@ -121,7 +121,7 @@ impl PackageSpecWriter for RpmSpecWriter { + let mut lines_to_write = BTreeSet::new(); + let last_tag_id = source_tags + .into_iter() +- .last() ++ .next_back() + .map(|tag| tag.id) + .unwrap_or_default(); + +-- +2.43.0 + diff --git a/0120-project-update-Cargo.lock.patch b/0120-project-update-Cargo.lock.patch new file mode 100644 index 0000000000000000000000000000000000000000..ee2c6a950ca6681320caea76aaa24aa424f55da9 --- /dev/null +++ b/0120-project-update-Cargo.lock.patch @@ -0,0 +1,26 @@ +From 62117683ff750b1b9209ca835a92606defad1198 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 17 Apr 2025 20:05:38 +0800 +Subject: [PATCH] project: update Cargo.lock + +Signed-off-by: renoseven +--- + Cargo.lock | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/Cargo.lock b/Cargo.lock +index 6ae9f36..b4798de 100644 +--- a/Cargo.lock ++++ b/Cargo.lock +@@ -1315,6 +1315,8 @@ dependencies = [ + "memmap2", + "memoffset", + "object", ++ "once_cell", ++ "regex", + "serde", + "syscare-common", + "typed-arena", +-- +2.43.0 + diff --git a/0121-project-change-compile-options.patch b/0121-project-change-compile-options.patch new file mode 100644 index 0000000000000000000000000000000000000000..5262e1c500a6d05913d368ec0c46cd8fd1b1a4dc --- /dev/null +++ b/0121-project-change-compile-options.patch @@ -0,0 +1,56 @@ +From 119b79e891ff2337b625db822294d278b93f22ad Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 23 Apr 2025 10:53:19 +0800 +Subject: [PATCH] project: change compile options + +Rust compiler options: +1. add "-C strip=symbols" +2. add "-C force-frame-pointers=true" + +Cargo.toml: +1. change opt-level from 's' to 3 +2. remove "debug-assertions = false" +3. remove "overflow-checks = false" + +Signed-off-by: renoseven +--- + CMakeLists.txt | 6 ++++-- + Cargo.toml | 4 +--- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index d8f3258..9d8b305 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -69,10 +69,12 @@ list(APPEND PROJECT_C_BUILD_FLAGS + ) + list(APPEND PROJECT_RUST_FLAGS + --cfg unsound_local_offset +- -C relocation_model=pic + -D warnings + -C link-arg=-s +- -C overflow_checks ++ -C strip=symbols ++ -C overflow_checks=yes ++ -C relocation_model=pic ++ -C force-frame-pointers=yes + -W rust_2021_incompatible_closure_captures + ) + +diff --git a/Cargo.toml b/Cargo.toml +index 07c796f..b22335f 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -10,8 +10,6 @@ members = [ + ] + + [profile.release] +-opt-level = 's' ++opt-level = 3 + debug = true + rpath = false +-debug-assertions = false +-overflow-checks = false +-- +2.43.0 + diff --git a/0122-syscare-build-fix-build-kernel-module-patch-failure.patch b/0122-syscare-build-fix-build-kernel-module-patch-failure.patch new file mode 100644 index 0000000000000000000000000000000000000000..212d613ebd964ffe8e2de0f433aabb0b81f443cc --- /dev/null +++ b/0122-syscare-build-fix-build-kernel-module-patch-failure.patch @@ -0,0 +1,60 @@ +From bb3dcae9a342b35283862aed1e5c3c4dd9f744f3 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Sun, 27 Apr 2025 10:36:44 +0800 +Subject: [PATCH] syscare-build: fix build kernel module patch failure + +add following environment variables: +1. OOT_MODULE=yes +2. USERMODBUILDDIR=%{oot_source_dir} + +Signed-off-by: renoseven +--- + .../src/patch/kernel_patch/kpatch_builder.rs | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/syscare-build/src/patch/kernel_patch/kpatch_builder.rs b/syscare-build/src/patch/kernel_patch/kpatch_builder.rs +index 202611d..7d44dd4 100644 +--- a/syscare-build/src/patch/kernel_patch/kpatch_builder.rs ++++ b/syscare-build/src/patch/kernel_patch/kpatch_builder.rs +@@ -12,7 +12,7 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::path::{Path, PathBuf}; ++use std::path::PathBuf; + + use anyhow::{Context, Result}; + use log::{info, Level}; +@@ -267,14 +267,17 @@ impl KernelPatchBuilder { + cmd_args + } + +- fn parse_kbuild_cmd_envs(&self, build_root: &Path) -> CommandEnvs { ++ fn parse_kbuild_cmd_envs(&self, kbuild_params: &KBuildParameters) -> CommandEnvs { + let mut cmd_envs = CommandEnvs::new(); + cmd_envs +- .env("CACHEDIR", build_root) ++ .env("CACHEDIR", &kbuild_params.patch_build_root) + .env("NO_PROFILING_CALLS", "yes") + .env("DISABLE_AFTER_LOAD", "yes") + .env("KEEP_JUMP_LABEL", "yes"); +- ++ if let Some(oot_source_dir) = &kbuild_params.oot_source_dir { ++ cmd_envs.env("OOT_MODULE", "yes"); ++ cmd_envs.env("USERMODBUILDDIR", oot_source_dir); ++ } + cmd_envs + } + +@@ -289,7 +292,7 @@ impl KernelPatchBuilder { + for mut kbuild_entity in kpatch_entities { + Command::new(KPATCH_BUILD_BIN) + .args(self.parse_kbuild_cmd_args(kbuild_params, &kbuild_entity)) +- .envs(self.parse_kbuild_cmd_envs(&kbuild_params.patch_build_root)) ++ .envs(self.parse_kbuild_cmd_envs(kbuild_params)) + .stdout(Level::Debug) + .run_with_output()? + .exit_ok()?; +-- +2.43.0 + diff --git a/0123-syscare-build-kmod-patch-entity-name-uses-shorter-uu.patch b/0123-syscare-build-kmod-patch-entity-name-uses-shorter-uu.patch new file mode 100644 index 0000000000000000000000000000000000000000..f3ce6ce20a574c49befdbafec5559d9ffc7113a7 --- /dev/null +++ b/0123-syscare-build-kmod-patch-entity-name-uses-shorter-uu.patch @@ -0,0 +1,107 @@ +From d652b14eeecac7a65caa1f611634081606c4229c Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 16 May 2025 12:50:16 +0800 +Subject: [PATCH] syscare-build: kmod patch entity name uses shorter uuid + +Signed-off-by: renoseven +--- + .../src/patch/kernel_patch/kpatch_builder.rs | 67 +++++++++++-------- + 1 file changed, 38 insertions(+), 29 deletions(-) + +diff --git a/syscare-build/src/patch/kernel_patch/kpatch_builder.rs b/syscare-build/src/patch/kernel_patch/kpatch_builder.rs +index 7d44dd4..18c59ef 100644 +--- a/syscare-build/src/patch/kernel_patch/kpatch_builder.rs ++++ b/syscare-build/src/patch/kernel_patch/kpatch_builder.rs +@@ -173,19 +173,23 @@ impl KernelPatchBuilder { + match &kbuild_params.oot_source_dir { + // Kernel patch + None => { +- let entity_uuid = Uuid::new_v4(); +- let entity_target = VMLINUX_FILE_NAME; +- let entity_name = format!("{}-{}", entity_target, entity_uuid); +- ++ let uuid = Uuid::new_v4(); ++ let uuid_short = uuid ++ .to_string() ++ .split_once('-') ++ .map(|s| s.0.to_string()) ++ .expect("Unexpected kernel patch uuid"); ++ ++ let patch_entity = PatchEntity { ++ uuid, ++ patch_name: concat_os!(VMLINUX_FILE_NAME, "-", uuid_short), ++ patch_target: VMLINUX_FILE_NAME.into(), ++ checksum: String::new(), ++ }; + entity_list.push(KernelPatchEntity { + source_dir: kbuild_params.kernel_source_dir.to_owned(), + module_path: None, +- patch_entity: PatchEntity { +- uuid: entity_uuid, +- patch_name: entity_name.into(), +- patch_target: entity_target.into(), +- checksum: String::default(), +- }, ++ patch_entity, + }); + } + // Kernel module patch +@@ -193,31 +197,36 @@ impl KernelPatchBuilder { + let module_list = + KernelPatchHelper::find_kernel_modules(&kbuild_params.pkg_build_dir) + .context("Failed to find any kernel module")?; +- let module_suffix = format!(".{}", KPATCH_SUFFIX); +- + for module_path in module_list { ++ let uuid = Uuid::new_v4(); ++ let uuid_short = uuid ++ .to_string() ++ .split_once('-') ++ .map(|s| s.0.to_string()) ++ .expect("Unexpected kernel module uuid"); + let file_name = module_path + .file_name() +- .context("Cannot get patch file name")?; +- let module_name = file_name +- .strip_suffix(&module_suffix) +- .context("Unexpected patch suffix")? +- .to_string_lossy() +- .replace(['.', '-'], "_"); +- +- let entity_uuid = Uuid::new_v4(); +- let entitiy_name = format!("{}-{}", module_name, entity_uuid); +- let entity_target = file_name.to_os_string(); +- ++ .expect("Unexpected kernel module file name"); ++ let module_name = { ++ let mut module_file = module_path.clone(); ++ module_file.set_extension(""); ++ ++ module_file ++ .file_name() ++ .expect("Unexpected kernel module name") ++ .replace(['.', '-'], "_") ++ }; ++ ++ let patch_entity = PatchEntity { ++ uuid, ++ patch_name: concat_os!(module_name, "-", uuid_short), ++ patch_target: file_name.into(), ++ checksum: String::new(), ++ }; + entity_list.push(KernelPatchEntity { + source_dir: oot_source_dir.to_owned(), + module_path: Some(module_path), +- patch_entity: PatchEntity { +- uuid: entity_uuid, +- patch_name: entitiy_name.into(), +- patch_target: entity_target.into(), +- checksum: String::default(), +- }, ++ patch_entity, + }); + } + } +-- +2.43.0 + diff --git a/0124-syscare-build-optimize-kpatch-build-arguments.patch b/0124-syscare-build-optimize-kpatch-build-arguments.patch new file mode 100644 index 0000000000000000000000000000000000000000..2a568b402ba2ed81252f74a744056759caf24df2 --- /dev/null +++ b/0124-syscare-build-optimize-kpatch-build-arguments.patch @@ -0,0 +1,168 @@ +From 8c8d355d023202b6568ff763e9d98c3ab152bf13 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 16 May 2025 15:34:01 +0800 +Subject: [PATCH] syscare-build: optimize kpatch-build arguments + +Signed-off-by: renoseven +--- + .../src/patch/kernel_patch/kpatch_builder.rs | 58 ++++++++++--------- + 1 file changed, 31 insertions(+), 27 deletions(-) + +diff --git a/syscare-build/src/patch/kernel_patch/kpatch_builder.rs b/syscare-build/src/patch/kernel_patch/kpatch_builder.rs +index 18c59ef..930e6fb 100644 +--- a/syscare-build/src/patch/kernel_patch/kpatch_builder.rs ++++ b/syscare-build/src/patch/kernel_patch/kpatch_builder.rs +@@ -43,7 +43,7 @@ struct KBuildParameters { + patch_build_root: PathBuf, + patch_output_dir: PathBuf, + kernel_source_dir: PathBuf, +- oot_source_dir: Option, ++ kmod_source_dir: Option, + config_file: PathBuf, + vmlinux_file: PathBuf, + patch_name: String, +@@ -61,7 +61,7 @@ struct KBuildParameters { + + struct KernelPatchEntity { + source_dir: PathBuf, +- module_path: Option, ++ kmod_path: Option, + patch_entity: PatchEntity, + } + +@@ -97,8 +97,8 @@ impl KernelPatchBuilder { + }, + ) + .context("Cannot find kernel source directory")?; ++ let kmod_source_dir = oot_module_entry.map(|entry| entry.build_source.clone()); + let kernel_debug_dir = &build_params.build_root.package.debuginfo; +- let oot_source_dir = oot_module_entry.map(|build_entry| build_entry.build_source.clone()); + + /* + * Kernel config: +@@ -147,7 +147,7 @@ impl KernelPatchBuilder { + patch_build_root, + patch_output_dir, + kernel_source_dir, +- oot_source_dir, ++ kmod_source_dir, + config_file, + vmlinux_file, + patch_name: build_params.patch_name.to_owned(), +@@ -170,7 +170,7 @@ impl KernelPatchBuilder { + ) -> Result> { + let mut entity_list = Vec::new(); + +- match &kbuild_params.oot_source_dir { ++ match &kbuild_params.kmod_source_dir { + // Kernel patch + None => { + let uuid = Uuid::new_v4(); +@@ -188,30 +188,30 @@ impl KernelPatchBuilder { + }; + entity_list.push(KernelPatchEntity { + source_dir: kbuild_params.kernel_source_dir.to_owned(), +- module_path: None, ++ kmod_path: None, + patch_entity, + }); + } + // Kernel module patch +- Some(oot_source_dir) => { +- let module_list = ++ Some(kmod_source_dir) => { ++ let kmod_list = + KernelPatchHelper::find_kernel_modules(&kbuild_params.pkg_build_dir) + .context("Failed to find any kernel module")?; +- for module_path in module_list { ++ for kmod_path in kmod_list { + let uuid = Uuid::new_v4(); + let uuid_short = uuid + .to_string() + .split_once('-') + .map(|s| s.0.to_string()) + .expect("Unexpected kernel module uuid"); +- let file_name = module_path ++ let file_name = kmod_path + .file_name() + .expect("Unexpected kernel module file name"); + let module_name = { +- let mut module_file = module_path.clone(); +- module_file.set_extension(""); ++ let mut kmod_file = kmod_path.clone(); ++ kmod_file.set_extension(""); + +- module_file ++ kmod_file + .file_name() + .expect("Unexpected kernel module name") + .replace(['.', '-'], "_") +@@ -224,8 +224,8 @@ impl KernelPatchBuilder { + checksum: String::new(), + }; + entity_list.push(KernelPatchEntity { +- source_dir: oot_source_dir.to_owned(), +- module_path: Some(module_path), ++ source_dir: kmod_source_dir.to_owned(), ++ kmod_path: Some(kmod_path), + patch_entity, + }); + } +@@ -250,20 +250,20 @@ impl KernelPatchBuilder { + .arg("--config") + .arg(&kbuild_params.config_file) + .arg("--vmlinux") +- .arg(&kbuild_params.vmlinux_file) +- .arg("--jobs") +- .arg(kbuild_params.jobs.to_string()) +- .arg("--output") +- .arg(&kbuild_params.patch_output_dir) +- .arg("--non-replace"); ++ .arg(&kbuild_params.vmlinux_file); + +- if let Some(oot_module) = &kbuild_entity.module_path { +- cmd_args.arg("--oot-module").arg(oot_module); ++ if let Some(kmod_path) = &kbuild_entity.kmod_path { ++ cmd_args.arg("--oot-module").arg(kmod_path); + cmd_args + .arg("--oot-module-src") + .arg(&kbuild_entity.source_dir); + } +- cmd_args.args(kbuild_params.patch_files.iter().map(|patch| &patch.path)); ++ ++ cmd_args ++ .arg("--jobs") ++ .arg(kbuild_params.jobs.to_string()) ++ .arg("--non-replace") ++ .arg("--skip-cleanup"); + + if kbuild_params.skip_compiler_check { + cmd_args.arg("--skip-compiler-check"); +@@ -271,7 +271,11 @@ impl KernelPatchBuilder { + if kbuild_params.verbose { + cmd_args.arg("--debug"); + } +- cmd_args.arg("--skip-cleanup"); ++ ++ cmd_args ++ .arg("--output") ++ .arg(&kbuild_params.patch_output_dir) ++ .args(kbuild_params.patch_files.iter().map(|f| &f.path)); + + cmd_args + } +@@ -283,9 +287,9 @@ impl KernelPatchBuilder { + .env("NO_PROFILING_CALLS", "yes") + .env("DISABLE_AFTER_LOAD", "yes") + .env("KEEP_JUMP_LABEL", "yes"); +- if let Some(oot_source_dir) = &kbuild_params.oot_source_dir { ++ if let Some(kmod_source_dir) = &kbuild_params.kmod_source_dir { + cmd_envs.env("OOT_MODULE", "yes"); +- cmd_envs.env("USERMODBUILDDIR", oot_source_dir); ++ cmd_envs.env("USERMODBUILDDIR", kmod_source_dir); + } + cmd_envs + } +-- +2.43.0 + diff --git a/0125-upatch-diff-sync-from-25.03-to-24.03-LTS.patch b/0125-upatch-diff-sync-from-25.03-to-24.03-LTS.patch new file mode 100644 index 0000000000000000000000000000000000000000..37fea1afe9860a6d7476742a5de637802514c91e --- /dev/null +++ b/0125-upatch-diff-sync-from-25.03-to-24.03-LTS.patch @@ -0,0 +1,268 @@ +From 8006398aaab567664062ed6edab5388b976b8c3f Mon Sep 17 00:00:00 2001 +From: Jvle +Date: Wed, 28 May 2025 11:12:32 +0800 +Subject: [PATCH] upatch-diff: sync from 25.03 to 24.03-LTS + +Signed-off-by: Jvle +--- + upatch-diff/create-diff-object.c | 28 +++++++++++++++++++++- + upatch-diff/elf-common.c | 41 +++++++++++++++++++++++++++++--- + upatch-diff/elf-common.h | 2 ++ + upatch-diff/elf-correlate.c | 6 +++++ + upatch-diff/elf-insn.c | 8 +++++++ + upatch-diff/elf-insn.h | 5 ++++ + upatch-diff/upatch-elf.c | 10 ++++++++ + upatch-diff/upatch-elf.h | 1 + + 8 files changed, 97 insertions(+), 4 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 9e4504e..886d8b2 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -434,7 +434,8 @@ static void replace_section_syms(struct upatch_elf *uelf) + !is_text_section(sym->sec) && + (rela->type == R_X86_64_32S || + rela->type == R_X86_64_32 || +- rela->type == R_AARCH64_ABS64) && ++ rela->type == R_AARCH64_ABS64 || ++ rela->type == R_RISCV_64) && + rela->addend == (long)sym->sec->sh.sh_size && + end == (long)sym->sec->sh.sh_size) { + ERROR("Relocation refer end of data sections."); +@@ -590,6 +591,12 @@ static void include_symbol(struct symbol *sym) + if ((sym->status != SAME) || (sym->type == STT_SECTION)) { + include_section(sym->sec); + } ++#ifdef __riscv ++ /* .L symbols not exist in EXE. If they are included, so are their sections. */ ++ else if (sym->sec && !sym->sec->include && !strncmp(sym->name, ".L", 2)) { ++ include_section(sym->sec); ++ } ++#endif + } + + static void include_section(struct section *sec) +@@ -749,6 +756,23 @@ static void verify_patchability(struct upatch_elf *uelf) + } + } + ++/* ++ * These types are for linker optimization and memory layout. ++ * They have no associated symbols and their names are empty ++ * string which would mismatch running-elf symbols in later ++ * lookup_relf(). Drop these useless items now. ++ */ ++static void rv_drop_useless_rela(struct section *relasec) ++{ ++ struct rela *rela, *saferela; ++ list_for_each_entry_safe(rela, saferela, &relasec->relas, list) ++ if (rela->type == R_RISCV_RELAX || rela->type == R_RISCV_ALIGN) { ++ list_del(&rela->list); ++ memset(rela, 0, sizeof(*rela)); ++ free(rela); ++ } ++} ++ + static void migrate_included_elements(struct upatch_elf *uelf_patched, + struct upatch_elf *uelf_out) + { +@@ -776,6 +800,8 @@ static void migrate_included_elements(struct upatch_elf *uelf_patched, + if (sec->sym && !sec->sym->include) { + sec->sym = NULL; // break link to non-included section symbol + } ++ } else if (uelf_patched->arch == RISCV64) { ++ rv_drop_useless_rela(sec); + } + } + +diff --git a/upatch-diff/elf-common.c b/upatch-diff/elf-common.c +index c5d8f61..22d12ca 100644 +--- a/upatch-diff/elf-common.c ++++ b/upatch-diff/elf-common.c +@@ -26,6 +26,35 @@ + + #include "elf-common.h" + ++#ifdef __riscv ++/* ++ * .L local symbols are named as ".L" + "class prefix" + "number". ++ * The numbers are volatile due to code change. ++ * Compare class prefix(composed of letters) only. ++ */ ++static int mangled_strcmp_dot_L(char *str1, char *str2) ++{ ++ if (!*str2 || strncmp(str2, ".L", 2)) { ++ return 1; ++ } ++ ++ /* RISCV_FAKE_LABEL_NAME matched exactly */ ++ if (!strcmp(str1, ".L0 ") || !strcmp(str2, ".L0 ")) { ++ return strcmp(str1, str2); ++ } ++ ++ char *p = str1 + 2; ++ char *q = str2 + 2; ++ while (*p < '0' || *p > '9') p++; ++ while (*q < '0' || *q > '9') q++; ++ if ((p - str1 != q - str2) || strncmp(str1, str2, (size_t)(p - str1))) { ++ return 1; ++ } ++ ++ return 0; ++} ++#endif ++ + static bool is_dynamic_debug_symbol(struct symbol *sym) + { + static const char *SEC_NAMES[] = { +@@ -122,6 +151,12 @@ int mangled_strcmp(char *str1, char *str2) + return strcmp(str1, str2); + } + ++#ifdef __riscv ++ if (!strncmp(str1, ".L", 2)) { ++ return mangled_strcmp_dot_L(str1, str2); ++ } ++#endif ++ + while (*str1 == *str2) { + if (!*str2) { + return 0; +@@ -180,7 +215,6 @@ int offset_of_string(struct list_head *list, char *name) + + ALLOC_LINK(string, list); + string->name = name; +- + return index; + } + +@@ -192,16 +226,17 @@ bool is_gcc6_localentry_bundled_sym(struct upatch_elf *uelf) + return false; + case X86_64: + return false; ++ case RISCV64: ++ return false; + default: + ERROR("unsupported arch"); + } +- + return false; + } + + bool is_mapping_symbol(struct upatch_elf *uelf, struct symbol *sym) + { +- if (uelf->arch != AARCH64) { ++ if ((uelf->arch != AARCH64) && (uelf->arch != RISCV64)) { + return false; + } + if (sym->name && sym->name[0] == '$' && +diff --git a/upatch-diff/elf-common.h b/upatch-diff/elf-common.h +index 3cebd32..f252cb9 100644 +--- a/upatch-diff/elf-common.h ++++ b/upatch-diff/elf-common.h +@@ -278,6 +278,8 @@ static inline unsigned int absolute_rela_type(struct upatch_elf *uelf) + return R_AARCH64_ABS64; + case X86_64: + return R_X86_64_64; ++ case RISCV64: ++ return R_RISCV_64; + default: + ERROR("unsupported arch"); + } +diff --git a/upatch-diff/elf-correlate.c b/upatch-diff/elf-correlate.c +index dcf3cfa..8e2f765 100644 +--- a/upatch-diff/elf-correlate.c ++++ b/upatch-diff/elf-correlate.c +@@ -83,6 +83,12 @@ void upatch_correlate_symbols(struct upatch_elf *uelf_source, + continue; + } + ++ /* on RISC-V: .L symbols should not change section */ ++ if (uelf_source->arch == RISCV64 && !strncmp(sym_orig->name, ".L", 2) && ++ sym_orig->sec && sym_orig->sec->twin != sym_patched->sec) { ++ continue; ++ } ++ + if (is_mapping_symbol(uelf_source, sym_orig)) { + continue; + } +diff --git a/upatch-diff/elf-insn.c b/upatch-diff/elf-insn.c +index 6fabd88..466a00c 100644 +--- a/upatch-diff/elf-insn.c ++++ b/upatch-diff/elf-insn.c +@@ -67,6 +67,8 @@ long rela_target_offset(struct upatch_elf *uelf, struct section *relasec, struct + long add_off; + + switch (uelf->arch) { ++ case RISCV64: ++ /* fall through */ + case AARCH64: + add_off = 0; + break; +@@ -106,6 +108,12 @@ unsigned int insn_length(struct upatch_elf *uelf, void *addr) + insn_init(&decoded_insn, addr, 1); + insn_get_length(&decoded_insn); + return decoded_insn.length; ++ case RISCV64: ++ /* LSB 2 bits distinguish insn size. Now only RV32, RVC supported. */ ++ if ((*(char *)addr & 0x3) == 0x3) { ++ return RISCV64_INSN_LEN_4; ++ } ++ return RISCV64_INSN_LEN_2; + default: + ERROR("unsupported arch"); + } +diff --git a/upatch-diff/elf-insn.h b/upatch-diff/elf-insn.h +index ac48ad0..fdbc2e3 100644 +--- a/upatch-diff/elf-insn.h ++++ b/upatch-diff/elf-insn.h +@@ -32,8 +32,13 @@ struct section; + struct rela; + struct insn; + ++// arm + #define ARM64_INSTR_LEN 4 + ++// riscv ++#define RISCV64_INSN_LEN_4 4 ++#define RISCV64_INSN_LEN_2 2 ++ + void rela_insn(const struct section *sec, const struct rela *rela, struct insn *insn); + + /* +diff --git a/upatch-diff/upatch-elf.c b/upatch-diff/upatch-elf.c +index c21b6ec..331504b 100644 +--- a/upatch-diff/upatch-elf.c ++++ b/upatch-diff/upatch-elf.c +@@ -321,6 +321,16 @@ void uelf_open(struct upatch_elf *uelf, const char *name) + case EM_X86_64: + uelf->arch = X86_64; + break; ++ case EM_RISCV: ++ /* ++ | Val | Macros | Description | ++ | 1 | ELFCLASS32 | riscv32 | ++ | 2 | ELFCLASS64 | riscv64 | ++ */ ++ if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { ++ uelf->arch = RISCV64; ++ } ++ break; + default: + ERROR("Unsupported architecture"); + } +diff --git a/upatch-diff/upatch-elf.h b/upatch-diff/upatch-elf.h +index 858cfa9..b34c1af 100644 +--- a/upatch-diff/upatch-elf.h ++++ b/upatch-diff/upatch-elf.h +@@ -41,6 +41,7 @@ struct symbol; + enum architecture { + X86_64 = 0x1 << 0, + AARCH64 = 0x1 << 1, ++ RISCV64 = 0x1 << 2, + }; + + enum data_source { +-- +2.43.0 + diff --git a/0042-riscv64-sync-riscv64-support-from-master-to-2503.patch b/0126-upatch-manage-sync-from-25.03-to-24.03-LTS.patch similarity index 71% rename from 0042-riscv64-sync-riscv64-support-from-master-to-2503.patch rename to 0126-upatch-manage-sync-from-25.03-to-24.03-LTS.patch index 148d896d6ac97df5ff4b3540eb4377f3ef89cf16..9a3cb8a03af8b7f83cdfac3b688fdfc4e5dd68d2 100644 --- a/0042-riscv64-sync-riscv64-support-from-master-to-2503.patch +++ b/0126-upatch-manage-sync-from-25.03-to-24.03-LTS.patch @@ -1,364 +1,25 @@ -From 0261efdbb718dd4850232940f9f9b7f156b19675 Mon Sep 17 00:00:00 2001 +From 240c0077a2b4b8a0898d29b2e68e595dbdc1dffc Mon Sep 17 00:00:00 2001 From: Jvle -Date: Mon, 3 Mar 2025 10:14:04 +0800 -Subject: [PATCH] riscv64: sync riscv64 support from master to 2503 - -sync from 64e3f03f467be4756d546f68ecbfce5ec93e0d42 +Date: Wed, 28 May 2025 11:13:19 +0800 +Subject: [PATCH] upatch-manage: sync from 25.03 to 24.03-LTS Signed-off-by: Jvle --- - README.md | 11 ++ - upatch-diff/create-diff-object.c | 28 ++- - upatch-diff/elf-common.c | 41 +++- - upatch-diff/elf-common.h | 2 + - upatch-diff/elf-compare.c | 4 +- - upatch-diff/elf-insn.c | 8 + - upatch-diff/elf-insn.h | 5 + - upatch-diff/running-elf.c | 1 - - upatch-diff/upatch-elf.c | 14 +- - upatch-diff/upatch-elf.h | 1 + upatch-manage/arch/riscv64/insn.h | 123 ++++++++++++ upatch-manage/arch/riscv64/process.h | 28 +++ - upatch-manage/arch/riscv64/ptrace.c | 207 ++++++++++++++++++++ - upatch-manage/arch/riscv64/relocation.c | 242 ++++++++++++++++++++++++ + upatch-manage/arch/riscv64/ptrace.c | 219 +++++++++++++++++++++ + upatch-manage/arch/riscv64/relocation.c | 246 ++++++++++++++++++++++++ upatch-manage/arch/riscv64/resolve.c | 154 +++++++++++++++ upatch-manage/upatch-patch.c | 22 +++ upatch-manage/upatch-ptrace.c | 4 + upatch-manage/upatch-ptrace.h | 8 + - 18 files changed, 894 insertions(+), 9 deletions(-) + 8 files changed, 804 insertions(+) create mode 100644 upatch-manage/arch/riscv64/insn.h create mode 100644 upatch-manage/arch/riscv64/process.h create mode 100644 upatch-manage/arch/riscv64/ptrace.c create mode 100644 upatch-manage/arch/riscv64/relocation.c create mode 100644 upatch-manage/arch/riscv64/resolve.c -diff --git a/README.md b/README.md -index 15d4d48..b34a6c1 100644 ---- a/README.md -+++ b/README.md -@@ -33,6 +33,8 @@ - - * 编译并安装 - -+ PS: 直接编译在应用补丁的时候会显示缺少依赖,建议通过rpm包安装 -+ - ```bash - git clone https://gitee.com/openeuler/syscare.git - cd syscare -@@ -41,6 +43,11 @@ - cmake -DCMAKE_INSTALL_PREFIX=/usr -DKERNEL_VERSION=$(uname -r) .. - make - make install -+ -+ mkdir -p /usr/lib/syscare/patches -+ systemctl daemon-reload -+ systemctl enable syscare -+ systemctl start syscare - ``` - - * 离线编译 -@@ -63,7 +70,11 @@ - ```bash - rpm -ivh syscare-*.rpm - ``` -+或者 - -+``` -+dnf install syscare-*.rpm -+``` - - - ## 使用说明 -diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c -index 1c14b7a..a06599e 100644 ---- a/upatch-diff/create-diff-object.c -+++ b/upatch-diff/create-diff-object.c -@@ -614,7 +614,8 @@ static void replace_section_syms(struct upatch_elf *uelf) - !is_text_section(sym->sec) && - (rela->type == R_X86_64_32S || - rela->type == R_X86_64_32 || -- rela->type == R_AARCH64_ABS64) && -+ rela->type == R_AARCH64_ABS64 || -+ rela->type == R_RISCV_64) && - rela->addend == (long)sym->sec->sh.sh_size && - end == (long)sym->sec->sh.sh_size) { - ERROR("Relocation refer end of data sections."); -@@ -759,6 +760,12 @@ static void include_symbol(struct symbol *sym) - if (sym->sec && (sym->type == STT_SECTION || sym->status != SAME)) { - include_section(sym->sec); - } -+#ifdef __riscv -+ /* .L symbols not exist in EXE. If they are included, so are their sections. */ -+ else if (sym->sec && !sym->sec->include && !strncmp(sym->name, ".L", 2)) { -+ include_section(sym->sec); -+ } -+#endif - } - - static void include_section(struct section *sec) -@@ -949,6 +956,23 @@ static void verify_patchability(struct upatch_elf *uelf) - } - } - -+/* -+ * These types are for linker optimization and memory layout. -+ * They have no associated symbols and their names are empty -+ * string which would mismatch running-elf symbols in later -+ * lookup_relf(). Drop these useless items now. -+ */ -+static void rv_drop_useless_rela(struct section *relasec) -+{ -+ struct rela *rela, *saferela; -+ list_for_each_entry_safe(rela, saferela, &relasec->relas, list) -+ if (rela->type == R_RISCV_RELAX || rela->type == R_RISCV_ALIGN) { -+ list_del(&rela->list); -+ memset(rela, 0, sizeof(*rela)); -+ free(rela); -+ } -+} -+ - static void migrate_included_elements(struct upatch_elf *uelf_patched, - struct upatch_elf *uelf_out) - { -@@ -975,6 +999,8 @@ static void migrate_included_elements(struct upatch_elf *uelf_patched, - - if (!is_rela_section(sec) && sec->secsym && !sec->secsym->include) { - sec->secsym = NULL; // break link to non-included section symbol -+ } else if (uelf_patched->arch == RISCV64) { -+ rv_drop_useless_rela(sec); - } - } - -diff --git a/upatch-diff/elf-common.c b/upatch-diff/elf-common.c -index 5aa35f1..3b62a5e 100644 ---- a/upatch-diff/elf-common.c -+++ b/upatch-diff/elf-common.c -@@ -26,6 +26,35 @@ - - #include "elf-common.h" - -+#ifdef __riscv -+/* -+ * .L local symbols are named as ".L" + "class prefix" + "number". -+ * The numbers are volatile due to code change. -+ * Compare class prefix(composed of letters) only. -+ */ -+static int mangled_strcmp_dot_L(char *str1, char *str2) -+{ -+ if (!*str2 || strncmp(str2, ".L", 2)) { -+ return 1; -+ } -+ -+ /* RISCV_FAKE_LABEL_NAME matched exactly */ -+ if (!strcmp(str1, ".L0 ") || !strcmp(str2, ".L0 ")) { -+ return strcmp(str1, str2); -+ } -+ -+ char *p = str1 + 2; -+ char *q = str2 + 2; -+ while (*p < '0' || *p > '9') p++; -+ while (*q < '0' || *q > '9') q++; -+ if ((p - str1 != q - str2) || strncmp(str1, str2, p - str1)) { -+ return 1; -+ } -+ -+ return 0; -+} -+#endif -+ - int mangled_strcmp(char *str1, char *str2) - { - /* -@@ -35,6 +64,12 @@ int mangled_strcmp(char *str1, char *str2) - return strcmp(str1, str2); - } - -+#ifdef __riscv -+ if (!strncmp(str1, ".L", 2)) { -+ return mangled_strcmp_dot_L(str1, str2); -+ } -+#endif -+ - while (*str1 == *str2) { - if (!*str2) { - return 0; -@@ -100,7 +135,6 @@ int offset_of_string(struct list_head *list, char *name) - - ALLOC_LINK(string, list); - string->name = name; -- - return index; - } - -@@ -112,16 +146,17 @@ bool is_gcc6_localentry_bundled_sym(struct upatch_elf *uelf) - return false; - case X86_64: - return false; -+ case RISCV64: -+ return false; - default: - ERROR("unsupported arch"); - } -- - return false; - } - - bool is_mapping_symbol(struct upatch_elf *uelf, struct symbol *sym) - { -- if (uelf->arch != AARCH64) { -+ if ((uelf->arch != AARCH64) && (uelf->arch != RISCV64)) { - return false; - } - if (sym->name && sym->name[0] == '$' && -diff --git a/upatch-diff/elf-common.h b/upatch-diff/elf-common.h -index bc2c1ac..0127314 100644 ---- a/upatch-diff/elf-common.h -+++ b/upatch-diff/elf-common.h -@@ -224,6 +224,8 @@ static inline unsigned int absolute_rela_type(struct upatch_elf *uelf) - return R_AARCH64_ABS64; - case X86_64: - return R_X86_64_64; -+ case RISCV64: -+ return R_RISCV_64; - default: - ERROR("unsupported arch"); - } -diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c -index 7ca6845..da31522 100644 ---- a/upatch-diff/elf-compare.c -+++ b/upatch-diff/elf-compare.c -@@ -175,7 +175,6 @@ bool upatch_handle_redis_line(const char *symname) - !strncmp(symname, "RedisModule__Assert", 19)) { - return true; - } -- - return false; - } - -@@ -362,6 +361,9 @@ static bool line_macro_change_only(struct upatch_elf *uelf, struct section *sec) - return line_macro_change_only_aarch64(uelf, sec); - case X86_64: - return line_macro_change_only_x86_64(uelf, sec); -+ case RISCV64: -+ /* TODO: not support */ -+ break; - default: - ERROR("unsupported arch"); - } -diff --git a/upatch-diff/elf-insn.c b/upatch-diff/elf-insn.c -index 8fcfc39..bb913dd 100644 ---- a/upatch-diff/elf-insn.c -+++ b/upatch-diff/elf-insn.c -@@ -66,6 +66,8 @@ long rela_target_offset(struct upatch_elf *uelf, struct section *relasec, struct - long add_off; - - switch (uelf->arch) { -+ case RISCV64: -+ /* fall through */ - case AARCH64: - add_off = 0; - break; -@@ -105,6 +107,12 @@ unsigned int insn_length(struct upatch_elf *uelf, void *addr) - insn_init(&decoded_insn, addr, 1); - insn_get_length(&decoded_insn); - return decoded_insn.length; -+ case RISCV64: -+ /* LSB 2 bits distinguish insn size. Now only RV32, RVC supported. */ -+ if ((*(char *)addr & 0x3) == 0x3) { -+ return RISCV64_INSN_LEN_4; -+ } -+ return RISCV64_INSN_LEN_2; - default: - ERROR("unsupported arch"); - } -diff --git a/upatch-diff/elf-insn.h b/upatch-diff/elf-insn.h -index f64ebe1..96d2225 100644 ---- a/upatch-diff/elf-insn.h -+++ b/upatch-diff/elf-insn.h -@@ -29,8 +29,13 @@ - #include "asm/insn.h" - #include "upatch-elf.h" - -+// arm - #define ARM64_INSTR_LEN 4 - -+// riscv -+#define RISCV64_INSN_LEN_4 4 -+#define RISCV64_INSN_LEN_2 2 -+ - void rela_insn(const struct section *sec, const struct rela *rela, struct insn *insn); - - /* -diff --git a/upatch-diff/running-elf.c b/upatch-diff/running-elf.c -index d9c1d6f..61c5057 100644 ---- a/upatch-diff/running-elf.c -+++ b/upatch-diff/running-elf.c -@@ -86,7 +86,6 @@ void relf_init(char *elf_name, struct running_elf *relf) - if (!data) { - ERROR("elf_getdata with error %s", elf_errmsg(0)); - } -- - relf->obj_nr = (int)(shdr.sh_size / shdr.sh_entsize); - relf->obj_syms = calloc((size_t)relf->obj_nr, sizeof(struct debug_symbol)); - if (!relf->obj_syms) { -diff --git a/upatch-diff/upatch-elf.c b/upatch-diff/upatch-elf.c -index a51f008..06a3123 100644 ---- a/upatch-diff/upatch-elf.c -+++ b/upatch-diff/upatch-elf.c -@@ -89,7 +89,7 @@ static void create_section_list(struct upatch_elf *uelf) - } - - log_debug("ndx %02d, data %p, size %zu, name %s\n", -- sec->index, sec->data->d_buf, sec->data->d_size, sec->name); -+ sec->index, sec->data->d_buf, sec->data->d_size, sec->name); - } - - if (elf_nextscn(uelf->elf, scn)) { -@@ -111,7 +111,6 @@ static void create_symbol_list(struct upatch_elf *uelf) - if (!symtab) { - ERROR("can't find symbol table"); - } -- - symbols_nr = (unsigned int)(symtab->sh.sh_size / symtab->sh.sh_entsize); - - log_debug("\n=== symbol list (%d entries) ===\n", symbols_nr); -@@ -130,7 +129,6 @@ static void create_symbol_list(struct upatch_elf *uelf) - if (!sym->name) { - ERROR("elf_strptr with error %s", elf_errmsg(0)); - } -- - sym->type = GELF_ST_TYPE(sym->sym.st_info); - sym->bind = GELF_ST_BIND(sym->sym.st_info); - -@@ -368,6 +366,16 @@ void upatch_elf_open(struct upatch_elf *uelf, const char *name) - case EM_X86_64: - uelf->arch = X86_64; - break; -+ case EM_RISCV: -+ /* -+ | Val | Macros | Description | -+ | 1 | ELFCLASS32 | riscv32 | -+ | 2 | ELFCLASS64 | riscv64 | -+ */ -+ if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { -+ uelf->arch = RISCV64; -+ } -+ break; - default: - ERROR("unsupported architecture here"); - } -diff --git a/upatch-diff/upatch-elf.h b/upatch-diff/upatch-elf.h -index 030feca..7597e8e 100644 ---- a/upatch-diff/upatch-elf.h -+++ b/upatch-diff/upatch-elf.h -@@ -126,6 +126,7 @@ struct symbol { - enum architecture { - X86_64 = 0x1 << 0, - AARCH64 = 0x1 << 1, -+ RISCV64 = 0x1 << 2, - }; - - struct upatch_elf { diff --git a/upatch-manage/arch/riscv64/insn.h b/upatch-manage/arch/riscv64/insn.h new file mode 100644 index 0000000..8ab4daf @@ -524,10 +185,10 @@ index 0000000..91926fa +#endif diff --git a/upatch-manage/arch/riscv64/ptrace.c b/upatch-manage/arch/riscv64/ptrace.c new file mode 100644 -index 0000000..c5691c9 +index 0000000..2ccdc9e --- /dev/null +++ b/upatch-manage/arch/riscv64/ptrace.c -@@ -0,0 +1,207 @@ +@@ -0,0 +1,219 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * upatch-manage @@ -552,6 +213,7 @@ index 0000000..c5691c9 +#include +#include +#include ++#include + +#include "upatch-ptrace.h" + @@ -630,19 +292,29 @@ index 0000000..c5691c9 + const void *data) +{ + struct user_regs_struct orig_regs, regs; -+ unsigned char orig_code[codelen]; ++ if (!codelen) { ++ log_error("Invalid codelen\n"); ++ return -1; ++ } ++ unsigned char *orig_code = (unsigned char *)malloc(sizeof(*orig_code) * codelen); ++ if (orig_code == NULL) { ++ log_error("Malloc orig_code failed\n"); ++ return -1; ++ } + long ret; + struct upatch_process *proc = pctx->proc; + unsigned long libc_base = proc->libc_base; + + ret = read_gregs(pctx->pid, &orig_regs); + if (ret < 0) { ++ free(orig_code); + return -1; + } + ret = upatch_process_mem_read(proc, libc_base, + (unsigned long *)orig_code, codelen); + if (ret < 0) { + log_error("can't peek original code - %d\n", pctx->pid); ++ free(orig_code); + return -1; + } + ret = upatch_process_mem_write(proc, (const unsigned long *)code, libc_base, @@ -683,6 +355,7 @@ index 0000000..c5691c9 +poke_back: + upatch_process_mem_write(proc, (unsigned long *)orig_code, libc_base, + codelen); ++ free(orig_code); + return ret; +} + @@ -737,10 +410,10 @@ index 0000000..c5691c9 +} diff --git a/upatch-manage/arch/riscv64/relocation.c b/upatch-manage/arch/riscv64/relocation.c new file mode 100644 -index 0000000..6c28bf8 +index 0000000..ba82599 --- /dev/null +++ b/upatch-manage/arch/riscv64/relocation.c -@@ -0,0 +1,242 @@ +@@ -0,0 +1,246 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * upatch-manage @@ -794,6 +467,9 @@ index 0000000..6c28bf8 + * The patch is a .o file, has only static relocations, all symbols + * have been resolved with our jump table act as got/plt. + */ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wconversion" ++#pragma GCC diagnostic ignored "-Wsign-conversion" +int apply_relocate_add(struct upatch_elf *uelf, unsigned int symindex, + unsigned int relsec) +{ @@ -983,9 +659,10 @@ index 0000000..6c28bf8 + (int)GELF_R_TYPE(rel[i].r_info), val); + return -ENOEXEC; +} ++#pragma GCC diagnostic pop diff --git a/upatch-manage/arch/riscv64/resolve.c b/upatch-manage/arch/riscv64/resolve.c new file mode 100644 -index 0000000..127fcc0 +index 0000000..0b4aa8b --- /dev/null +++ b/upatch-manage/arch/riscv64/resolve.c @@ -0,0 +1,154 @@ @@ -1056,9 +733,9 @@ index 0000000..127fcc0 + index * sizeof(struct upatch_jmp_table_entry)); +} + -+static unsigned long setup_got_table(struct upatch_elf *uelf, -+ unsigned long jmp_addr, -+ unsigned long tls_addr) ++unsigned long setup_got_table(struct upatch_elf *uelf, ++ unsigned long jmp_addr, ++ unsigned long tls_addr) +{ + struct upatch_jmp_table_entry *table = + uelf->core_layout.kbase + uelf->jmp_offs; @@ -1079,7 +756,7 @@ index 0000000..127fcc0 +} + +unsigned long insert_plt_table(struct upatch_elf *uelf, struct object_file *obj, -+ unsigned long r_type, unsigned long addr) ++ unsigned long r_type __attribute__((unused)), unsigned long addr) +{ + unsigned long jmp_addr = 0xffffffff; + unsigned long tls_addr = 0xffffffff; @@ -1144,10 +821,10 @@ index 0000000..127fcc0 + return elf_addr; +} diff --git a/upatch-manage/upatch-patch.c b/upatch-manage/upatch-patch.c -index 4a1e568..c57ae74 100644 +index 4b1b1be..fd2c5f2 100644 --- a/upatch-manage/upatch-patch.c +++ b/upatch-manage/upatch-patch.c -@@ -476,6 +476,23 @@ static int complete_info(struct upatch_elf *uelf, struct object_file *obj, +@@ -475,6 +475,23 @@ static int complete_info(struct upatch_elf *uelf, struct object_file *obj, upatch_func->addr = upatch_funcs_addr[i].addr; upatch_func->addr.old_addr += uelf->relf->load_bias; @@ -1160,8 +837,8 @@ index 4a1e568..c57ae74 100644 + * new_insn field is only 8 bytes. We can only jump into + * +-2G ranges. Here do the check. + */ -+ long offset = upatch_func->addr.new_addr - upatch_func->addr.old_addr; -+ if (offset >= RISCV_MAX_JUMP_RANGE || offset < -RISCV_MAX_JUMP_RANGE) { ++ long riscv_offset = (long)(upatch_func->addr.new_addr - upatch_func->addr.old_addr); ++ if (riscv_offset >= RISCV_MAX_JUMP_RANGE || riscv_offset < -RISCV_MAX_JUMP_RANGE) { + log_error("new_addr=%lx old_addr=%lx exceed +-2G range\n", + upatch_func->addr.new_addr, upatch_func->addr.old_addr); + goto out; @@ -1171,7 +848,7 @@ index 4a1e568..c57ae74 100644 ret = upatch_process_mem_read(obj->proc, upatch_func->addr.old_addr, &upatch_func->old_insn, get_origin_insn_len()); if (ret) { -@@ -484,7 +501,12 @@ static int complete_info(struct upatch_elf *uelf, struct object_file *obj, +@@ -483,7 +500,12 @@ static int complete_info(struct upatch_elf *uelf, struct object_file *obj, goto out; } @@ -1226,5 +903,5 @@ index 8f36565..f2503cf 100644 #endif -- -2.34.1 +2.43.0 diff --git a/0127-CMake-fix-Werror-cast-align-for-riscv64.patch b/0127-CMake-fix-Werror-cast-align-for-riscv64.patch new file mode 100644 index 0000000000000000000000000000000000000000..a43d992abfae010a29c36f39e23806863edb43ba --- /dev/null +++ b/0127-CMake-fix-Werror-cast-align-for-riscv64.patch @@ -0,0 +1,42 @@ +From ba6fee40405c9baabcd878a68501646e5ecff143 Mon Sep 17 00:00:00 2001 +From: Jvle +Date: Wed, 23 Apr 2025 17:08:09 +0800 +Subject: [PATCH] CMake: fix -Werror=cast-align for riscv64 + +Signed-off-by: Jvle +--- + CMakeLists.txt | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 9d8b305..95a917f 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -62,11 +62,23 @@ list(APPEND PROJECT_C_BUILD_FLAGS + -DBUILD_VERSION="${PROJECT_BUILD_VERSION}" -D_FORTIFY_SOURCE=2 + -Wtrampolines -Wformat=2 -Wstrict-prototypes -Wdate-time + -Wstack-usage=8192 -Wfloat-equal -Wswitch-default +- -Wshadow -Wconversion -Wcast-qual -Wcast-align -Wunused -Wundef ++ -Wshadow -Wconversion -Wcast-qual -Wunused -Wundef + -funsigned-char -fstack-protector-all -fpic -fpie -ftrapv + -fstack-check -freg-struct-return -fno-canonical-system-headers + -fno-common -pipe -fdebug-prefix-map=old=new + ) ++ ++# The -Werror=cast-align compiler flag causes issues on riscv64 GCC, ++# while the same operations do not error on aarch64. This appears to be ++# a compiler-specific problem. Temporarily disable this option as a ++# workaround since applying fixes would require intrusive code changes ++# across multiple files. ++if(NOT ARCH STREQUAL "riscv64") ++ list(APPEND PROJECT_C_BUILD_FLAGS ++ -Wcast-align ++ ) ++endif() ++ + list(APPEND PROJECT_RUST_FLAGS + --cfg unsound_local_offset + -D warnings +-- +2.43.0 + diff --git a/0128-upatch-build-fix-compile-failure-for-lower-rust-vers.patch b/0128-upatch-build-fix-compile-failure-for-lower-rust-vers.patch new file mode 100644 index 0000000000000000000000000000000000000000..0799757eab0256393f3ffb1f51ea276b2bfb56b9 --- /dev/null +++ b/0128-upatch-build-fix-compile-failure-for-lower-rust-vers.patch @@ -0,0 +1,26 @@ +From 56106014c3928e0cad1fa94ef2b2fd3abf5bec90 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 12 Jun 2025 18:45:00 +0800 +Subject: [PATCH] upatch-build: fix compile failure for lower rust version + +Signed-off-by: renoseven +--- + upatch-build/src/dwarf.rs | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/upatch-build/src/dwarf.rs b/upatch-build/src/dwarf.rs +index 4934a7a..fe0821c 100644 +--- a/upatch-build/src/dwarf.rs ++++ b/upatch-build/src/dwarf.rs +@@ -112,7 +112,7 @@ impl ProducerParser { + let section_name = section_id.name(); + let section = match file.section_by_name(section_name) { + Some(section) => section, +- None => return Ok(EndianRcSlice::new(Rc::default(), endian)), ++ None => return Ok(EndianRcSlice::new(Rc::new([]), endian)), + }; + + let mut section_data = section +-- +2.43.0 + diff --git a/0038-metadata-viewer-add-component.patch b/0129-metadata-viewer-add-component.patch similarity index 98% rename from 0038-metadata-viewer-add-component.patch rename to 0129-metadata-viewer-add-component.patch index 95b92d8db932882296482b86f02efe05279cabbe..1a755017b894575828c8e79af192f8806751797e 100644 --- a/0038-metadata-viewer-add-component.patch +++ b/0129-metadata-viewer-add-component.patch @@ -1,4 +1,4 @@ -From d903d529a5d503d688aa41276240408e747c3366 Mon Sep 17 00:00:00 2001 +From d8db0142d5f0240d3e33a5707bd878a9a81c3d89 Mon Sep 17 00:00:00 2001 From: renoseven Date: Wed, 12 Feb 2025 14:40:32 +0800 Subject: [PATCH] metadata-viewer: add component @@ -18,10 +18,10 @@ Signed-off-by: renoseven create mode 100644 metadata-viewer/src/main.rs diff --git a/CMakeLists.txt b/CMakeLists.txt -index ca9fdfe..573752a 100644 +index 95a917f..f0a46c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -171,6 +171,7 @@ install( +@@ -190,6 +190,7 @@ install( ${RUST_OUTPUT_DIR}/upatch-helper ${RUST_OUTPUT_DIR}/upatch-cc ${RUST_OUTPUT_DIR}/upatch-c++ @@ -30,7 +30,7 @@ index ca9fdfe..573752a 100644 OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE diff --git a/Cargo.toml b/Cargo.toml -index 07c796f..52a4255 100644 +index b22335f..1373560 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,8 @@ members = [ @@ -280,5 +280,5 @@ index 0000000..8097788 + Ok(()) +} -- -2.34.1 +2.43.0 diff --git a/0039-metadata-generator-add-component.patch b/0130-metadata-generator-add-component.patch similarity index 99% rename from 0039-metadata-generator-add-component.patch rename to 0130-metadata-generator-add-component.patch index cdf4b0d8d581edccf3db592f0275851d4880f472..15921533cf8cac6d3ea42acf770ec69130793539 100644 --- a/0039-metadata-generator-add-component.patch +++ b/0130-metadata-generator-add-component.patch @@ -1,4 +1,4 @@ -From cce391fe5268723a890fdf9de78144ec046bd8d2 Mon Sep 17 00:00:00 2001 +From ffbf8957e442867baa21495e705a064d8bd8b8d3 Mon Sep 17 00:00:00 2001 From: renoseven Date: Thu, 13 Feb 2025 11:27:26 +0800 Subject: [PATCH] metadata-generator: add component @@ -18,10 +18,10 @@ Signed-off-by: renoseven create mode 100644 metadata-generator/src/main.rs diff --git a/CMakeLists.txt b/CMakeLists.txt -index 573752a..2f658b9 100644 +index f0a46c9..e1a9051 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -172,6 +172,7 @@ install( +@@ -191,6 +191,7 @@ install( ${RUST_OUTPUT_DIR}/upatch-cc ${RUST_OUTPUT_DIR}/upatch-c++ ${RUST_OUTPUT_DIR}/metadata-viewer @@ -30,7 +30,7 @@ index 573752a..2f658b9 100644 OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE diff --git a/Cargo.toml b/Cargo.toml -index 52a4255..a514352 100644 +index 1373560..eb7ea7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ @@ -529,5 +529,5 @@ index 0000000..b37a5e3 + Ok(()) +} -- -2.34.1 +2.43.0 diff --git a/generate_package.sh b/generate_package.sh index a6f328e1a76b5d03db8c26db043ac3ea2c74909a..6fd8d2b2bda6edba8eea41ee6e00c5df90221cd9 100755 --- a/generate_package.sh +++ b/generate_package.sh @@ -1,47 +1,130 @@ -#!/bin/bash -e +#!/bin/bash +set -euo pipefail -readonly SPEC_FILE="$(find . -name '*.spec' | head -n 1)" +readonly REPO_URL="git@gitee.com:openeuler/syscare.git" +readonly REPO_NAME="$(basename "${REPO_URL}" .git)" -readonly REPO_NAME="$(basename ${SPEC_FILE} | sed 's/.spec//')" -readonly REPO_URL="https://gitee.com/openeuler/${REPO_NAME}" -readonly REPO_BRANCH="$(git branch --show-current | sed 's/-LTS.*//')" -readonly REPO_VERSION="$(grep Version ${SPEC_FILE} | head -n 1 | awk -F ' ' '{print $NF}')" +readonly CURR_DIR="$(dirname "$(realpath "$0")")" +readonly OUTPUT_DIR="${CURR_DIR}" -readonly PKG_NAME="${REPO_NAME}-${REPO_VERSION}" -readonly PKG_DIR="$(realpath ./${PKG_NAME})" +####################################### +# 1. Parse package info +####################################### +readonly RPM_SPEC="${CURR_DIR}/${REPO_NAME}.spec" +if [[ ! -f "${RPM_SPEC}" ]]; then + echo "Error: Cannot find rpm spec file '${RPM_SPEC}'" >&2 + exit 1 +fi -echo "Preparing..." -rm -rf ./${REPO_NAME} ./${PKG_NAME} -rm -f ./*.tar.gz +readonly RPM_NAME="$(awk '/^Name:[[:space:]]+/ {print $2; exit}' "${RPM_SPEC}" | sed 's/%{?*}//g')" +if [[ -z "${RPM_NAME}" ]]; then + echo "Error: Failed to parse rpm package name" >&2 + exit 1 +fi -echo "--------------------------" +readonly RPM_VERSION="$(awk '/^Version:[[:space:]]+/ {print $2; exit}' "${RPM_SPEC}" | sed 's/%{?*}//g')" +if [[ -z "${RPM_VERSION}" ]]; then + echo "Error: Failed to parse rpm package version" >&2 + exit 1 +fi + +####################################### +# 2. Parse target branch +####################################### +readonly TARGET_BRANCH=$( + branch="$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse --short HEAD 2>/dev/null)" + if [[ "${branch}" != *-Next ]]; then + printf '%s' "${branch}" + exit 0 + fi + + prefix="${branch%-Next}" + candidate="$( + git branch --list "${prefix}*" --format='%(refname:short)' \ + | grep -vF -- "${branch}" \ + | sort -V \ + | tail -n1 + )" + + if [[ -n "${candidate}" ]]; then + printf '%s' "${candidate}" + else + printf '%s' "${branch}" + fi +) + +####################################### +# 3. Show detail info +####################################### +echo "---------------------------------" echo "Name: ${REPO_NAME}" -echo "Branch: ${REPO_BRANCH}" -echo "--------------------------" +echo "Branch: ${TARGET_BRANCH}" +echo "---------------------------------" + +####################################### +# 4. Clone source code +####################################### +readonly SOURCE_DIR_NAME="${RPM_NAME}-${RPM_VERSION}" +readonly SOURCE_DIR="${CURR_DIR}/${SOURCE_DIR_NAME}" echo "Cloning source code..." -git clone ${REPO_URL} -b ${REPO_BRANCH} ${PKG_NAME} +rm -rf "${SOURCE_DIR}" +git clone "${REPO_URL}" -b "${TARGET_BRANCH}" "${SOURCE_DIR_NAME}" +echo "" -echo "Vendoring dependencies..." -pushd ${PKG_DIR} > /dev/null +####################################### +# 5. Vendor dependencies +####################################### +readonly CARGO_DIR="${SOURCE_DIR}/.cargo" +readonly VENDOR_DIR="${SOURCE_DIR}/vendor" +readonly CONFIG_TOML="${CARGO_DIR}/config.toml" -cargo vendor --quiet --respect-source-config --sync Cargo.toml +echo "Vendoring dependencies..." +( + cd "${SOURCE_DIR}" + cargo vendor --respect-source-config --sync Cargo.toml +) -mkdir -p .cargo -cat << EOF > .cargo/config.toml +rm -rf "${CARGO_DIR}" +mkdir -p "${CARGO_DIR}" +cat << EOF > "${CONFIG_TOML}" [source.crates-io] replace-with = "vendored-sources" [source.vendored-sources] directory = "vendor" EOF +echo "" + +####################################### +# 6. Compress vendor package +####################################### +echo "Compressing vendor package..." +readonly VENDOR_PKG="${CURR_DIR}/vendor.tar.gz" + +rm -f "${VENDOR_PKG}" +( + cd "${SOURCE_DIR}" + tar -czvf "${VENDOR_PKG}" ".cargo" "vendor" +) + +rm -rf "${CARGO_DIR}" +rm -rf "${VENDOR_DIR}" +echo "" -popd > /dev/null +####################################### +# 7. Compress source package +####################################### +echo "Compressing source package..." +readonly SOURCE_PKG="${CURR_DIR}/${SOURCE_DIR_NAME}.tar.gz" -echo "Compressing package..." -tar -czf ./${PKG_NAME}.tar.gz ${PKG_NAME} +tar -czvf "${SOURCE_PKG}" "${SOURCE_DIR_NAME}" +echo "" +####################################### +# 8. Clean up +####################################### echo "Cleaning up..." -rm -rf ${PKG_DIR} +rm -rf "${SOURCE_DIR}" echo "Done" diff --git a/generate_patches.sh b/generate_patches.sh index 69e31b4c0024e91d216b0b4ae57c0707e537575a..edd68d537e0a7254468b1ddfee97ca7bbd5415a0 100755 --- a/generate_patches.sh +++ b/generate_patches.sh @@ -1,54 +1,136 @@ -#!/bin/bash -e +#!/bin/bash +set -euo pipefail -readonly SPEC_FILE="$(find . -name '*.spec' | head -n 1)" +readonly REPO_URL="git@gitee.com:openeuler/syscare.git" +readonly REPO_NAME="$(basename "${REPO_URL}" .git)" -readonly REPO_NAME="$(basename ${SPEC_FILE} | sed 's/.spec//')" -readonly REPO_URL="https://gitee.com/openeuler/${REPO_NAME}" -readonly REPO_BRANCH="$(git branch --show-current | sed 's/-LTS.*//')" -readonly REPO_VERSION="$(grep Version ${SPEC_FILE} | head -n 1 | awk -F ' ' '{print $NF}')" +readonly CURR_DIR="$(dirname "$(realpath "$0")")" +readonly OUTPUT_DIR="${CURR_DIR}" -readonly PKG_NAME="${REPO_NAME}-${REPO_VERSION}" -readonly PKG_DIR="$(realpath ./${PKG_NAME})" +####################################### +# 1. Parse package info +####################################### +readonly RPM_SPEC="${CURR_DIR}/${REPO_NAME}.spec" +if [[ ! -f "${RPM_SPEC}" ]]; then + echo "Error: Cannot find rpm spec file '${RPM_SPEC}'" >&2 + exit 1 +fi -readonly PATCH_DIR="$(pwd)" +readonly RPM_NAME="$(awk '/^Name:[[:space:]]+/ {print $2; exit}' "${RPM_SPEC}" | sed 's/%{?*}//g')" +if [[ -z "${RPM_NAME}" ]]; then + echo "Error: Failed to parse rpm package name" >&2 + exit 1 +fi -echo "Preparing..." -rm -rf ${PKG_DIR} -rm -f ./*.patch +readonly RPM_VERSION="$(awk '/^Version:[[:space:]]+/ {print $2; exit}' "${RPM_SPEC}" | sed 's/%{?*}//g')" +if [[ -z "${RPM_VERSION}" ]]; then + echo "Error: Failed to parse rpm package version" >&2 + exit 1 +fi -tar -xf ./${PKG_NAME}.tar.gz +####################################### +# 2. Decompress source package +####################################### +readonly SOURCE_PKG="${CURR_DIR}/${RPM_NAME}-${RPM_VERSION}.tar.gz" +if [[ ! -f "${SOURCE_PKG}" ]]; then + echo "Error: Cannot find source package '${SOURCE_PKG}'" >&2 + exit 1 +fi -pushd ${PKG_DIR} > /dev/null -readonly REPO_BASELINE="$(git rev-parse --short HEAD)" -popd > /dev/null +readonly SOURCE_DIR="${CURR_DIR}/${RPM_NAME}-${RPM_VERSION}" +rm -rf "${SOURCE_DIR}" 2>/dev/null -echo "------------------------------" -echo "Name: ${REPO_NAME}" -echo "Branch: ${REPO_BRANCH}" -echo "Baseline: ${REPO_BASELINE}" -echo "------------------------------" +tar -xzf "${SOURCE_PKG}" || { + echo "Error: Failed to decompress source package" >&2 + exit 1 +} +if [[ ! -d "${SOURCE_DIR}" ]]; then + echo "Error: Cannot find source directory '${SOURCE_DIR}'" >&2 + exit 1 +fi +####################################### +# 3. Parse source package baseline +####################################### +readonly SOURCE_BASELINE="$( + cd "${SOURCE_DIR}" + git rev-parse --short HEAD 2>/dev/null +)" +if [[ -z "${SOURCE_BASELINE}" ]]; then + echo "Error: Failed to parse source package baseline" >&2 + exit 1 +fi + +####################################### +# 4. Parse target branch +####################################### +readonly TARGET_BRANCH=$( + branch="$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse --short HEAD 2>/dev/null)" + if [[ "${branch}" != *-Next ]]; then + printf '%s' "${branch}" + exit 0 + fi + + prefix="${branch%-Next}" + candidate="$( + git branch --list "${prefix}*" --format='%(refname:short)' \ + | grep -vF -- "${branch}" \ + | sort -V \ + | tail -n1 + )" + + if [[ -n "${candidate}" ]]; then + printf '%s' "${candidate}" + else + printf '%s' "${branch}" + fi +) + +####################################### +# 5. Show detail info +####################################### +echo "---------------------------------" +echo "Name: ${RPM_NAME}-${RPM_VERSION}" +echo "Branch: ${TARGET_BRANCH}" +echo "Baseline: ${SOURCE_BASELINE}" +echo "---------------------------------" +echo "" + +####################################### +# 6. Sync repository +####################################### echo "Syncing with remote..." -pushd ${PKG_DIR} > /dev/null -git fetch origin -popd > /dev/null +( + cd "${SOURCE_DIR}" + git remote remove origin 2>/dev/null || true + git remote add origin "${REPO_URL}" + git fetch origin +) +echo "" +####################################### +# 7. Format patches +####################################### echo "Generating patches..." -# format patches -pushd ${PKG_DIR} > /dev/null -git checkout -q origin/${REPO_BRANCH} -git format-patch -qN -o ${PATCH_DIR} ${REPO_BASELINE} -popd > /dev/null - -# print patch list -patch_list="$(find . -maxdepth 1 -name "*.patch" | sort)" -for patch_file in ${patch_list}; do - patch_name="$(basename ${patch_file})" - patch_id="$(echo ${patch_name} | awk -F '-' '{print $1}')" - echo "Patch${patch_id}: ${patch_name}" -done +( + cd "${SOURCE_DIR}" + + git checkout -q --track "origin/${TARGET_BRANCH}" + git format-patch -qN -o "${OUTPUT_DIR}" "${SOURCE_BASELINE}" + + readarray -d '' patch_files < <(find "${OUTPUT_DIR}" -maxdepth 1 -name "*.patch" -print0 | sort -z) + for patch_file in "${patch_files[@]}"; do + patch_name="${patch_file##*/}" + patch_id="${patch_name%%-*}" + printf 'Patch%s: %s\n' "${patch_id}" "${patch_name}" + done +) +echo "" +####################################### +# 8. Clean up +####################################### echo "Cleaning up..." -rm -rf ${PKG_DIR} +rm -rf "${SOURCE_DIR}" echo "Done" diff --git a/syscare-1.2.2.tar.gz b/syscare-1.2.2.tar.gz index ed3bbd7c6fe14754fd367c9095fde16fabf6db0b..31f3e5d299421ea84d958b49d647e610176deb9f 100644 Binary files a/syscare-1.2.2.tar.gz and b/syscare-1.2.2.tar.gz differ diff --git a/syscare.spec b/syscare.spec index 3c5af8e948fc4a7b490514a7c017bcbe513c248d..2a4b95a93e561cb9c795366227dbc6935c9527d6 100644 --- a/syscare.spec +++ b/syscare.spec @@ -5,11 +5,12 @@ ############################################ Name: syscare Version: 1.2.2 -Release: 5 +Release: 6 Summary: System hot-fix service License: MulanPSL-2.0 and GPL-2.0-only URL: https://gitee.com/openeuler/syscare Source0: %{name}-%{version}.tar.gz +Source1: vendor.tar.gz BuildRequires: cmake >= 3.14 make BuildRequires: rust >= 1.51 cargo >= 1.51 @@ -56,16 +57,99 @@ Patch0034: 0034-syscared-impl-syscare-rescan-command.patch Patch0035: 0035-syscare-impl-syscare-rescan-command.patch Patch0036: 0036-syscared-impl-log-config.patch Patch0037: 0037-syscared-impl-patch-blacklist.patch -Patch0038: 0038-metadata-viewer-add-component.patch -Patch0039: 0039-metadata-generator-add-component.patch -Patch0040: 0040-project-update-Cargo.lock.patch -Patch0041: 0041-syscared-fix-patch-target-is-blocked-issue.patch -Patch0042: 0042-riscv64-sync-riscv64-support-from-master-to-2503.patch -Patch0043: 0043-syscare-build-fix-detect-incorrect-kernel-source-dir.patch -Patch0044: 0044-upatch-manage-fix-compile-failure.patch -Patch0045: 0045-syscared-fix-kmod-patch-conflicts-with-itself-issue.patch -Patch0046: 0046-common-fix-failed-to-acquire-flock-issue.patch -Patch0047: 0047-syscare-rewrite-syscare-cli.patch +Patch0038: 0038-syscared-fix-patch-target-is-blocked-issue.patch +Patch0039: 0039-syscare-build-fix-detect-incorrect-kernel-source-dir.patch +Patch0040: 0040-upatch-manage-fix-compile-failure.patch +Patch0041: 0041-syscared-fix-kmod-patch-conflicts-with-itself-issue.patch +Patch0042: 0042-common-fix-failed-to-acquire-flock-issue.patch +Patch0043: 0043-syscare-rewrite-syscare-cli.patch +Patch0044: 0044-upatch-diff-fix-static-local-var-correlate.patch +Patch0045: 0045-upatch-manage-fix-first-object-cannot-find-mem-hole.patch +Patch0046: 0046-syscare-fix-request-is-unrecognized-issue.patch +Patch0047: 0047-upatch-manage-fix-alloc-patch-memory-permission-deni.patch +Patch0048: 0048-upatch-diff-remove-line-macro-related-functions.patch +Patch0049: 0049-upatch-build-support-override-line-macros.patch +Patch0050: 0050-syscare-build-add-keep-line-macros-argument.patch +Patch0051: 0051-common-fs-glob-wildcard-path-includes-current-direct.patch +Patch0052: 0052-upatch-build-only-replace-line-macros-for-source-fil.patch +Patch0053: 0053-upatch-manage-container_of-use-void-instead-of-char.patch +Patch0054: 0054-CMake-move-EXECUTE_PROCESS-from-upatch-manage-to-top.patch +Patch0055: 0055-upatch-diff-impl-section-type-checking.patch +Patch0056: 0056-upatch-diff-allow-string-literal-section-being-inclu.patch +Patch0057: 0057-upatch-diff-fix-code-logic-when-drop-rela.patch +Patch0058: 0058-upatch-diff-fix-cannot-detect-some-changes-issue.patch +Patch0059: 0059-upatch-diff-fix-.text-section-change-does-not-includ.patch +Patch0060: 0060-upatch-diff-fix-.data.rel-section-is-changed-issue.patch +Patch0061: 0061-upatch-diff-rewrite-patch-verification-logic.patch +Patch0062: 0062-upatch-diff-rewrite-symbol-include-logic.patch +Patch0063: 0063-upatch-diff-allow-.rodata-section-sh_addralign-chang.patch +Patch0064: 0064-upatch-diff-allow-.debug_-section-header-changes.patch +Patch0065: 0065-upatch-diff-allow-tls-variable-changes.patch +Patch0066: 0066-upatch-diff-allow-delete-local-static-variables.patch +Patch0067: 0067-upatch-diff-fix-lookup_relf-returns-wrong-sympos-iss.patch +Patch0068: 0068-upatch-diff-change-include-ignored-grouped-data-type.patch +Patch0069: 0069-upatch-diff-compare-symbol-by-checking-it-s-section-.patch +Patch0070: 0070-upatch-diff-ignore-debug-sections.patch +Patch0071: 0071-upatch-diff-allow-sh_flags-sh_addralign-changes.patch +Patch0072: 0072-upatch-diff-fix-null-symbol-lookup-error.patch +Patch0073: 0073-upatch-diff-use-kpatch-way-to-deal-with-static-local.patch +Patch0074: 0074-upatch-diff-remove-intermediate-sections.patch +Patch0075: 0075-upatch-diff-rewrite-local-symbol-matching-logic.patch +Patch0076: 0076-upatch-diff-skip-local-symbols-like-__func__.xxx.patch +Patch0077: 0077-upatch-diff-warning-on-no-function-changed-when-crea.patch +Patch0078: 0078-upatch-diff-treat-.L-symbol-as-special-symbol.patch +Patch0079: 0079-upatch-diff-allow-object-symbol-size-changes.patch +Patch0080: 0080-upatch-diff-optimize-log.patch +Patch0081: 0081-upatch-diff-enrich-error-message.patch +Patch0082: 0082-upatch-diff-improve-initializing-object-handling.patch +Patch0083: 0083-upatch-diff-fix-uelf-list-insert-order-issue.patch +Patch0084: 0084-upatch-diff-reorganize-relf-struct.patch +Patch0085: 0085-upatch-diff-fix-cannot-find-local-symbol-in-relf-iss.patch +Patch0086: 0086-upatch-diff-fix-coredump-in-checking-symbol.patch +Patch0087: 0087-upatch-diff-fix-compare-common-section-symbol-failur.patch +Patch0088: 0088-upatch-diff-optimize-debug-output.patch +Patch0089: 0089-upatch-diff-support-text-section-offset.patch +Patch0090: 0090-upatch-diff-remove-match_local_symbols.patch +Patch0091: 0091-upatch-diff-rewrite-uelf-relf-struct.patch +Patch0092: 0092-upatch-diff-fix-access-freed-section-data-issue.patch +Patch0093: 0093-syscared-fix-kernel-compatibility-check-is-not-worki.patch +Patch0094: 0094-syscare-build-add-debug-option-to-kpatch-build.patch +Patch0095: 0095-Fix-invalid-url-for-syscare-build-readme.patch +Patch0096: 0096-doc-sync-master-document.patch +Patch0097: 0097-common-rewrite-fs-glob.patch +Patch0098: 0098-common-rewrite-fs-components.patch +Patch0099: 0099-syscare-adapt-common-fs-changes.patch +Patch0100: 0100-syscared-adapt-common-fs-changes.patch +Patch0101: 0101-upatch-helper-optimize-compiler-flags.patch +Patch0102: 0102-upatch-helper-support-clang-compiler.patch +Patch0103: 0103-upatch-helper-support-cross-compilation.patch +Patch0104: 0104-upatch-helper-add-Werror-uninitialized-for-clang.patch +Patch0105: 0105-upatch-build-execute-clean-before-first-time-buildin.patch +Patch0106: 0106-upatch-build-rewrite-compiler-detection.patch +Patch0107: 0107-upatch-build-adapt-fs-glob-changes.patch +Patch0108: 0108-upatch-build-binary-dir-supports-wildcard-path.patch +Patch0109: 0109-upatch-build-adapt-common-fs-changes.patch +Patch0110: 0110-upatch-build-format-code.patch +Patch0111: 0111-upatch-build-fix-upatch-id-parsing-failure.patch +Patch0112: 0112-upatch-build-rename-patch-note-object.patch +Patch0113: 0113-upatch-build-rewrite-object-collecting.patch +Patch0114: 0114-upatch-build-fix-unable-to-find-object-linker-error.patch +Patch0115: 0115-upatch-build-warning-on-finding-patched-object-failu.patch +Patch0116: 0116-upatch-build-try-hardlink-before-copy-files.patch +Patch0117: 0117-upatch-build-optimize-code.patch +Patch0118: 0118-upatch-build-support-text-section-offset.patch +Patch0119: 0119-syscare-build-fix-clippy-warnings.patch +Patch0120: 0120-project-update-Cargo.lock.patch +Patch0121: 0121-project-change-compile-options.patch +Patch0122: 0122-syscare-build-fix-build-kernel-module-patch-failure.patch +Patch0123: 0123-syscare-build-kmod-patch-entity-name-uses-shorter-uu.patch +Patch0124: 0124-syscare-build-optimize-kpatch-build-arguments.patch +Patch0125: 0125-upatch-diff-sync-from-25.03-to-24.03-LTS.patch +Patch0126: 0126-upatch-manage-sync-from-25.03-to-24.03-LTS.patch +Patch0127: 0127-CMake-fix-Werror-cast-align-for-riscv64.patch +Patch0128: 0128-upatch-build-fix-compile-failure-for-lower-rust-vers.patch +Patch0129: 0129-metadata-viewer-add-component.patch +Patch0130: 0130-metadata-generator-add-component.patch ############### Description ################ %description @@ -74,7 +158,7 @@ The host can fix the system problem without rebooting. ############## BuildPreparare ############## %prep -%autosetup -p1 +%autosetup -p1 -a1 ################## Build ################### %build @@ -166,14 +250,24 @@ Syscare patch building toolset. %attr(555,root,root) /usr/libexec/syscare/upatch-build %attr(555,root,root) /usr/libexec/syscare/upatch-diff %attr(555,root,root) /usr/libexec/syscare/upatch-helper -%attr(555,root,root) /usr/libexec/syscare/upatch-cc -%attr(555,root,root) /usr/libexec/syscare/upatch-c++ %attr(555,root,root) /usr/libexec/syscare/metadata-generator +/usr/libexec/syscare/upatch-cc +/usr/libexec/syscare/upatch-c++ ############################################ ################ Change log ################ ############################################ %changelog +* Tue Jun 03 2025 renoseven - 1.2.2-6 +- feature: upatch supports overridding line macros +- bugfix: fix upatch id parsing error +- bugfix: fix upatch object linker detection failure +- bugfix: fix kernel module build failure +- bugfix: fix kernel patch name length limitation +- bugfix: fix multiple upatch-diff issues +- bugfix: fix multiple upatch-manage issues +- rpm: extract vendor from syscare-1.2.2.tar.gz to vendor.tar.gz + * Thu Mar 13 2025 renoseven - 1.2.2-5 - feature: support riscv64 - feature: support 'syscare rescan' command diff --git a/vendor.tar.gz b/vendor.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..a3d01bb8522de70ca3f0353dc514afff09b1b240 Binary files /dev/null and b/vendor.tar.gz differ