97
97
* /tmp/jitted-PID-0.so: [headers][.text][unwind_info][padding]
98
98
* /tmp/jitted-PID-1.so: [headers][.text][unwind_info][padding]
99
99
*
100
- * The padding size (0x100) is chosen to accommodate typical unwind info sizes
101
- * while maintaining 16-byte alignment requirements.
100
+ * The padding size is now calculated automatically during initialization
101
+ * based on the actual unwind information requirements.
102
102
*/
103
- #define PERF_JIT_CODE_PADDING 0x100
104
103
105
104
/* Convenient access to the global trampoline API state */
106
105
#define trampoline_api _PyRuntime.ceval.perf.trampoline_api
@@ -646,6 +645,8 @@ static void elfctx_append_uleb128(ELFObjectContext* ctx, uint32_t v) {
646
645
// DWARF EH FRAME GENERATION
647
646
// =============================================================================
648
647
648
+ static void elf_init_ehframe (ELFObjectContext * ctx );
649
+
649
650
/*
650
651
* Initialize DWARF .eh_frame section for a code region
651
652
*
@@ -660,6 +661,23 @@ static void elfctx_append_uleb128(ELFObjectContext* ctx, uint32_t v) {
660
661
* Args:
661
662
* ctx: ELF object context containing code size and buffer pointers
662
663
*/
664
+ static size_t calculate_eh_frame_size (void ) {
665
+ /* Calculate the EH frame size for the trampoline function */
666
+ extern void * _Py_trampoline_func_start ;
667
+ extern void * _Py_trampoline_func_end ;
668
+
669
+ size_t code_size = (char * )& _Py_trampoline_func_end - (char * )& _Py_trampoline_func_start ;
670
+
671
+ ELFObjectContext ctx ;
672
+ char buffer [1024 ]; // Buffer for DWARF data (1KB should be sufficient)
673
+ ctx .code_size = code_size ;
674
+ ctx .startp = ctx .p = (uint8_t * )buffer ;
675
+ ctx .fde_p = NULL ;
676
+
677
+ elf_init_ehframe (& ctx );
678
+ return ctx .p - ctx .startp ;
679
+ }
680
+
663
681
static void elf_init_ehframe (ELFObjectContext * ctx ) {
664
682
uint8_t * p = ctx -> p ;
665
683
uint8_t * framep = p ; // Remember start of frame data
@@ -856,7 +874,7 @@ static void elf_init_ehframe(ELFObjectContext* ctx) {
856
874
*
857
875
* The FDE describes unwinding information specific to this function.
858
876
* It references the CIE and provides function-specific CFI instructions.
859
- *
877
+ *
860
878
* The PC-relative offset is calculated after the entire EH frame is built
861
879
* to ensure accurate positioning relative to the synthesized DSO layout.
862
880
*/
@@ -914,11 +932,11 @@ static void elf_init_ehframe(ELFObjectContext* ctx) {
914
932
)
915
933
916
934
ctx -> p = p ; // Update context pointer to end of generated data
917
-
935
+
918
936
/* Calculate and update the PC-relative offset in the FDE
919
- *
937
+ *
920
938
* When perf processes the jitdump, it creates a synthesized DSO with this layout:
921
- *
939
+ *
922
940
* Synthesized DSO Memory Layout:
923
941
* ┌─────────────────────────────────────────────────────────────┐ < code_start
924
942
* │ Code Section │
@@ -936,33 +954,33 @@ static void elf_init_ehframe(ELFObjectContext* ctx) {
936
954
* │ │ CFI Instructions... │ │
937
955
* │ └─────────────────────────────────────────────────────┘ │
938
956
* ├─────────────────────────────────────────────────────────────┤ < reference_point
939
- * │ EhFrameHeader │
957
+ * │ EhFrameHeader │
940
958
* │ (navigation metadata) │
941
959
* └─────────────────────────────────────────────────────────────┘
942
- *
960
+ *
943
961
* The PC offset field in the FDE must contain the distance from itself to code_start:
944
- *
962
+ *
945
963
* distance = code_start - fde_pc_field
946
- *
964
+ *
947
965
* Where:
948
966
* fde_pc_field_location = reference_point - eh_frame_size + fde_offset_in_frame
949
967
* code_start_location = reference_point - eh_frame_size - round_up(code_size, 8)
950
- *
968
+ *
951
969
* Therefore:
952
970
* distance = code_start_location - fde_pc_field_location
953
971
* = (ref - eh_frame_size - rounded_code_size) - (ref - eh_frame_size + fde_offset_in_frame)
954
972
* = -rounded_code_size - fde_offset_in_frame
955
973
* = -(round_up(code_size, 8) + fde_offset_in_frame)
956
974
*
957
975
* Note: fde_offset_in_frame is the offset from EH frame start to the PC offset field,
958
- *
976
+ *
959
977
*/
960
978
if (ctx -> fde_p != NULL ) {
961
979
int32_t fde_offset_in_frame = (ctx -> fde_p - ctx -> startp );
962
980
int32_t rounded_code_size = round_up (ctx -> code_size , 8 );
963
981
int32_t pc_relative_offset = - (rounded_code_size + fde_offset_in_frame );
964
-
965
-
982
+
983
+
966
984
// Update the PC-relative offset in the FDE
967
985
* (int32_t * )ctx -> fde_p = pc_relative_offset ;
968
986
}
@@ -1066,8 +1084,10 @@ static void* perf_map_jit_init(void) {
1066
1084
/* Initialize code ID counter */
1067
1085
perf_jit_map_state .code_id = 0 ;
1068
1086
1069
- /* Configure trampoline API with padding information */
1070
- trampoline_api .code_padding = PERF_JIT_CODE_PADDING ;
1087
+ /* Calculate padding size based on actual unwind info requirements */
1088
+ size_t eh_frame_size = calculate_eh_frame_size ();
1089
+ size_t unwind_data_size = sizeof (EhFrameHeader ) + eh_frame_size ;
1090
+ trampoline_api .code_padding = round_up (unwind_data_size , 16 );
1071
1091
1072
1092
return & perf_jit_map_state ;
1073
1093
}
@@ -1175,7 +1195,7 @@ static void perf_map_jit_write_entry(void *state, const void *code_addr,
1175
1195
ev2 .unwind_data_size = sizeof (EhFrameHeader ) + eh_frame_size ;
1176
1196
1177
1197
/* Verify we don't exceed our padding budget */
1178
- assert (ev2 .unwind_data_size <= PERF_JIT_CODE_PADDING );
1198
+ assert (ev2 .unwind_data_size <= trampoline_api . code_padding );
1179
1199
1180
1200
ev2 .eh_frame_hdr_size = sizeof (EhFrameHeader );
1181
1201
ev2 .mapped_size = round_up (ev2 .unwind_data_size , 16 ); // 16-byte alignment
0 commit comments