xref: /aosp_15_r20/external/mesa3d/src/amd/common/ac_rgp_elf_object_pack.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2021 Advanced Micro Devices, Inc.
3  *
4  * SPDX-License-Identifier: MIT
5  */
6 
7 /**
8  * \file ac_rgp_elf_object_pack.c
9  *
10  * This file provides functions to create elf object for rgp profiling.
11  * The functions in this file create 64bit elf code object irrespective
12  * of if the driver is compiled as 32 or 64 bit.
13  */
14 
15 #include <stdint.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <libelf.h>
19 #include "ac_msgpack.h"
20 #include "ac_rgp.h"
21 
22 #include "util/bitscan.h"
23 #include "util/u_math.h"
24 
25 #ifndef EM_AMDGPU
26 // Old distributions may not have this enum constant
27 #define EM_AMDGPU 224
28 #endif
29 
30 char hw_stage_string[RGP_HW_STAGE_MAX][4] = {
31    ".vs",
32    ".ls",
33    ".hs",
34    ".es",
35    ".gs",
36    ".ps",
37    ".cs"
38 };
39 
40 char hw_stage_symbol_string[RGP_HW_STAGE_MAX][16] = {
41    "_amdgpu_vs_main",
42    "_amdgpu_ls_main",
43    "_amdgpu_hs_main",
44    "_amdgpu_es_main",
45    "_amdgpu_gs_main",
46    "_amdgpu_ps_main",
47    "_amdgpu_cs_main"
48 };
49 
50 static const char *
get_api_stage_string(gl_shader_stage stage)51 get_api_stage_string(gl_shader_stage stage)
52 {
53    switch (stage) {
54    case MESA_SHADER_VERTEX:
55       return".vertex";
56    case MESA_SHADER_TESS_CTRL:
57       return".hull";
58    case MESA_SHADER_TESS_EVAL:
59       return".domain";
60    case MESA_SHADER_GEOMETRY:
61       return".geometry";
62    case MESA_SHADER_FRAGMENT:
63       return".pixel";
64    case MESA_SHADER_MESH:
65       return ".mesh";
66    case MESA_SHADER_TASK:
67       return ".task";
68    default:
69       /* RT shaders are implemented using compute HW stages, so use ".compute"
70          for any stage other than graphics stages */
71       return".compute";
72    }
73 }
74 
75 static const char *
get_hw_stage_symbol(struct rgp_code_object_record * record,unsigned index)76 get_hw_stage_symbol(struct rgp_code_object_record *record, unsigned index)
77 {
78    if (record->is_rt)
79       return record->shader_data[index].rt_shader_name;
80    else
81       return hw_stage_symbol_string[record->shader_data[index].hw_stage];
82 }
83 
84 static const char *
rt_subtype_from_stage(gl_shader_stage stage)85 rt_subtype_from_stage(gl_shader_stage stage)
86 {
87    switch (stage) {
88    case MESA_SHADER_RAYGEN:
89       return "RayGeneration";
90    case MESA_SHADER_MISS:
91       return "Miss";
92    case MESA_SHADER_CLOSEST_HIT:
93       return "ClosestHit";
94    case MESA_SHADER_CALLABLE:
95       return "Callable";
96    case MESA_SHADER_INTERSECTION:
97       return "Traversal";
98    /* There are also AnyHit and Intersection subtypes, but on RADV
99     * these are inlined into the traversal shader */
100    default:
101       return "Unknown";
102    }
103 }
104 
105 /**
106  * rgp profiler requires data for few variables stored in msgpack format
107  * in notes section. This function writes the data from
108  * struct rgp_code_object_record to elf object in msgpack format.
109  * for msgpack specification refer to
110  * github.com/msgpack/msgpack/blob/master/spec.md
111  */
112 static void
ac_rgp_write_msgpack(FILE * output,struct rgp_code_object_record * record,uint32_t * written_size)113 ac_rgp_write_msgpack(FILE *output,
114                      struct rgp_code_object_record *record,
115                      uint32_t *written_size)
116 {
117    struct ac_msgpack msgpack;
118    uint32_t num_shaders;
119    uint32_t i;
120    uint32_t mask;
121 
122    num_shaders = util_bitcount(record->shader_stages_mask);
123 
124    ac_msgpack_init(&msgpack);
125 
126    ac_msgpack_add_fixmap_op(&msgpack, 2);
127       ac_msgpack_add_fixstr(&msgpack, "amdpal.version");
128       ac_msgpack_add_fixarray_op(&msgpack, 2);
129          ac_msgpack_add_uint(&msgpack, 2);
130          ac_msgpack_add_uint(&msgpack, 1);
131 
132       ac_msgpack_add_fixstr(&msgpack, "amdpal.pipelines");
133       ac_msgpack_add_fixarray_op(&msgpack, 1);
134          ac_msgpack_add_fixmap_op(&msgpack, 6 + record->is_rt);
135 
136             /* 1
137              * This not used in RGP but data needs to be present
138              */
139             ac_msgpack_add_fixstr(&msgpack, ".spill_threshold");
140             ac_msgpack_add_uint(&msgpack, 0xffff);
141 
142             /* 2
143              * This not used in RGP but data needs to be present
144              */
145             ac_msgpack_add_fixstr(&msgpack, ".user_data_limit");
146             ac_msgpack_add_uint(&msgpack, 32);
147 
148             /* 3 */
149             ac_msgpack_add_fixstr(&msgpack, ".shaders");
150             ac_msgpack_add_fixmap_op(&msgpack, num_shaders);
151                mask = record->shader_stages_mask;
152                while(mask) {
153                   i = u_bit_scan(&mask);
154                   ac_msgpack_add_fixstr(&msgpack, get_api_stage_string(i));
155                   ac_msgpack_add_fixmap_op(&msgpack, 2);
156                   ac_msgpack_add_fixstr(&msgpack, ".api_shader_hash");
157                   ac_msgpack_add_fixarray_op(&msgpack, 2);
158                      ac_msgpack_add_uint(&msgpack,
159                                          record->shader_data[i].hash[0]);
160                      ac_msgpack_add_uint(&msgpack, 0);
161                   ac_msgpack_add_fixstr(&msgpack, ".hardware_mapping");
162                   ac_msgpack_add_fixarray_op(&msgpack, 1);
163                      ac_msgpack_add_fixstr(&msgpack, hw_stage_string[
164                                            record->shader_data[i].hw_stage]);
165                }
166 
167             /* 4 */
168             ac_msgpack_add_fixstr(&msgpack, ".hardware_stages");
169             ac_msgpack_add_fixmap_op(&msgpack,
170                                      record->num_shaders_combined);
171                mask = record->shader_stages_mask;
172                while(mask) {
173                   i = u_bit_scan(&mask);
174 
175                   if (record->shader_data[i].is_combined)
176                      continue;
177 
178                   ac_msgpack_add_fixstr(&msgpack, hw_stage_string[
179                                         record->shader_data[i].hw_stage]);
180                   ac_msgpack_add_fixmap_op(&msgpack, 6);
181                      ac_msgpack_add_fixstr(&msgpack, ".entry_point");
182                      ac_msgpack_add_fixstr(&msgpack, get_hw_stage_symbol(record, i));
183 
184                      ac_msgpack_add_fixstr(&msgpack, ".sgpr_count");
185                      ac_msgpack_add_uint(&msgpack,
186                                          record->shader_data[i].sgpr_count);
187 
188                      ac_msgpack_add_fixstr(&msgpack, ".vgpr_count");
189                      ac_msgpack_add_uint(&msgpack,
190                                          record->shader_data[i].vgpr_count);
191 
192                      ac_msgpack_add_fixstr(&msgpack, ".scratch_memory_size");
193                      ac_msgpack_add_uint(&msgpack,
194                                          record->shader_data[i].scratch_memory_size);
195 
196                      ac_msgpack_add_fixstr(&msgpack, ".wavefront_size");
197                      ac_msgpack_add_uint(&msgpack,
198                                          record->shader_data[i].wavefront_size);
199 
200                      ac_msgpack_add_fixstr(&msgpack, ".lds_size");
201                      ac_msgpack_add_uint(&msgpack, record->shader_data[i].lds_size);
202                }
203 
204             /* 5 */
205             ac_msgpack_add_fixstr(&msgpack, ".internal_pipeline_hash");
206             ac_msgpack_add_fixarray_op(&msgpack, 2);
207                ac_msgpack_add_uint(&msgpack, record->pipeline_hash[0]);
208                ac_msgpack_add_uint(&msgpack, record->pipeline_hash[1]);
209 
210             /* 6 */
211             ac_msgpack_add_fixstr(&msgpack, ".api");
212             ac_msgpack_add_fixstr(&msgpack, "Vulkan");
213 
214             if (record->is_rt) {
215                   /* 7 */
216                   ac_msgpack_add_fixstr(&msgpack, ".shader_functions");
217                   ac_msgpack_add_fixmap_op(&msgpack, num_shaders);
218                      mask = record->shader_stages_mask;
219                      while (mask) {
220                         i = u_bit_scan(&mask);
221                         ac_msgpack_add_fixstr(&msgpack, record->shader_data[i].rt_shader_name);
222                         ac_msgpack_add_fixmap_op(&msgpack, 7);
223                            ac_msgpack_add_fixstr(&msgpack, ".stack_frame_size_in_bytes");
224                            ac_msgpack_add_uint(&msgpack, record->shader_data[i].rt_stack_size);
225 
226                            ac_msgpack_add_fixstr(&msgpack, ".shader_subtype");
227                            ac_msgpack_add_fixstr(&msgpack, rt_subtype_from_stage(i));
228                            ac_msgpack_add_fixstr(&msgpack, ".api_shader_hash");
229                            ac_msgpack_add_fixarray_op(&msgpack, 2);
230                               ac_msgpack_add_uint(&msgpack, record->pipeline_hash[0]);
231                               ac_msgpack_add_uint(&msgpack, record->pipeline_hash[1]);
232 
233                            ac_msgpack_add_fixstr(&msgpack, ".sgpr_count");
234                            ac_msgpack_add_uint(&msgpack, record->shader_data[i].sgpr_count);
235 
236                            ac_msgpack_add_fixstr(&msgpack, ".vgpr_count");
237                            ac_msgpack_add_uint(&msgpack, record->shader_data[i].vgpr_count);
238 
239                            ac_msgpack_add_fixstr(&msgpack, ".lds_size");
240                            ac_msgpack_add_uint(&msgpack, record->shader_data[i].lds_size);
241 
242                            ac_msgpack_add_fixstr(&msgpack, ".scratch_memory_size");
243                            ac_msgpack_add_uint(&msgpack,
244                                                record->shader_data[i].scratch_memory_size);
245                      }
246             }
247    ac_msgpack_resize_if_required(&msgpack, 4 - (msgpack.offset % 4));
248    msgpack.offset = ALIGN(msgpack.offset, 4);
249    fwrite(msgpack.mem, 1, msgpack.offset, output);
250    *written_size = msgpack.offset;
251    ac_msgpack_destroy(&msgpack);
252 }
253 
254 
255 static uint32_t
get_lowest_shader(uint32_t * shader_stages_mask,struct rgp_code_object_record * record,struct rgp_shader_data ** rgp_shader_data)256 get_lowest_shader(uint32_t *shader_stages_mask,
257                   struct rgp_code_object_record *record,
258                   struct rgp_shader_data **rgp_shader_data)
259 {
260    uint32_t i, lowest = 0;
261    uint32_t mask;
262    uint64_t base_address = -1;
263 
264    if (*shader_stages_mask == 0)
265       return false;
266 
267    mask = *shader_stages_mask;
268    while(mask) {
269       i = u_bit_scan(&mask);
270       if (record->shader_data[i].is_combined) {
271          *shader_stages_mask = *shader_stages_mask & ~((uint32_t)1 << i);
272          continue;
273       }
274       if (base_address > record->shader_data[i].base_address) {
275          lowest = i;
276          base_address = record->shader_data[i].base_address;
277       }
278    }
279 
280    *shader_stages_mask = *shader_stages_mask & ~((uint32_t)1 << lowest);
281    *rgp_shader_data = &record->shader_data[lowest];
282    return true;
283 }
284 
285 /**
286  *  write the shader code into elf object in text section
287  */
288 static void
ac_rgp_file_write_elf_text(FILE * output,uint32_t * elf_size_calc,struct rgp_code_object_record * record,uint32_t * text_size)289 ac_rgp_file_write_elf_text(FILE *output, uint32_t *elf_size_calc,
290                            struct rgp_code_object_record *record,
291                            uint32_t *text_size)
292 {
293    struct rgp_shader_data *rgp_shader_data = NULL;
294    struct rgp_shader_data *prev_rgp_shader_data = NULL;
295    uint32_t symbol_offset = 0;
296    uint32_t mask = record->shader_stages_mask;
297    static bool warn_once = true;
298 
299    while(get_lowest_shader(&mask, record, &rgp_shader_data)) {
300       if (prev_rgp_shader_data) {
301          uint32_t code_offset = rgp_shader_data->base_address -
302                                 prev_rgp_shader_data->base_address;
303          uint32_t gap_between_code = code_offset -
304                                      prev_rgp_shader_data->code_size;
305          symbol_offset += code_offset;
306          if (gap_between_code > 0x10000 && warn_once) {
307             fprintf(stderr, "Warning: shader code far from previous "
308                             "(%d bytes apart). The rgp capture file "
309                             "might be very large.\n", gap_between_code);
310             warn_once = false;
311          }
312 
313          fseek(output, gap_between_code, SEEK_CUR);
314          *elf_size_calc += gap_between_code;
315       }
316 
317       rgp_shader_data->elf_symbol_offset = symbol_offset;
318       fwrite(rgp_shader_data->code, 1, rgp_shader_data->code_size, output);
319       *elf_size_calc += rgp_shader_data->code_size;
320       prev_rgp_shader_data = rgp_shader_data;
321    }
322 
323    symbol_offset += rgp_shader_data->code_size;
324    uint32_t aligned = ALIGN(symbol_offset, 256) - symbol_offset;
325    fseek(output, aligned, SEEK_CUR);
326    *elf_size_calc += aligned;
327    *text_size = symbol_offset + aligned;
328 }
329 
330 /*
331  * hardcoded index for string table and text section in elf object.
332  * While populating section header table, the index order should
333  * be strictly followed.
334  */
335 #define RGP_ELF_STRING_TBL_SEC_HEADER_INDEX 1
336 #define RGP_ELF_TEXT_SEC_HEADER_INDEX 2
337 
338 /*
339  * hardcode the string table so that is a single write to output.
340  * the strings are in a structure so that it is easy to get the offset
341  * of given string in string table.
342  */
343 struct ac_rgp_elf_string_table {
344    char null[sizeof("")];
345    char strtab[sizeof(".strtab")];
346    char text[sizeof(".text")];
347    char symtab[sizeof(".symtab")];
348    char note[sizeof(".note")];
349    char vs_main[sizeof("_amdgpu_vs_main")];
350    char ls_main[sizeof("_amdgpu_ls_main")];
351    char hs_main[sizeof("_amdgpu_hs_main")];
352    char es_main[sizeof("_amdgpu_es_main")];
353    char gs_main[sizeof("_amdgpu_gs_main")];
354    char ps_main[sizeof("_amdgpu_ps_main")];
355    char cs_main[sizeof("_amdgpu_cs_main")];
356 };
357 
358 struct ac_rgp_elf_string_table rgp_elf_strtab = {
359    .null = "",
360    .strtab = ".strtab",
361    .text = ".text",
362    .symtab = ".symtab",
363    .note = ".note",
364    .vs_main = "_amdgpu_vs_main",
365    .ls_main = "_amdgpu_ls_main",
366    .hs_main = "_amdgpu_hs_main",
367    .es_main = "_amdgpu_es_main",
368    .gs_main = "_amdgpu_gs_main",
369    .ps_main = "_amdgpu_ps_main",
370    .cs_main = "_amdgpu_cs_main",
371 };
372 
373 uint32_t rgp_elf_hw_stage_string_offset[RGP_HW_STAGE_MAX] = {
374    (uintptr_t)((struct ac_rgp_elf_string_table*)0)->vs_main,
375    (uintptr_t)((struct ac_rgp_elf_string_table*)0)->ls_main,
376    (uintptr_t)((struct ac_rgp_elf_string_table*)0)->hs_main,
377    (uintptr_t)((struct ac_rgp_elf_string_table*)0)->es_main,
378    (uintptr_t)((struct ac_rgp_elf_string_table*)0)->gs_main,
379    (uintptr_t)((struct ac_rgp_elf_string_table*)0)->ps_main,
380    (uintptr_t)((struct ac_rgp_elf_string_table*)0)->cs_main,
381 };
382 
383 
384 static void
ac_rgp_file_write_elf_symbol_table(FILE * output,uint32_t * elf_size_calc,struct rgp_code_object_record * record,uint32_t * symbol_table_size)385 ac_rgp_file_write_elf_symbol_table(FILE *output, uint32_t *elf_size_calc,
386                                    struct rgp_code_object_record *record,
387                                    uint32_t *symbol_table_size)
388 {
389    Elf64_Sym elf_sym;
390    uint32_t i;
391    uint32_t mask = record->shader_stages_mask;
392 
393    memset(&elf_sym, 0x00, sizeof(elf_sym));
394    fwrite(&elf_sym, 1, sizeof(elf_sym), output);
395 
396    uint32_t rt_name_offset = 0;
397 
398    while(mask) {
399       i = u_bit_scan(&mask);
400       if (record->shader_data[i].is_combined)
401          continue;
402 
403       if (record->is_rt) {
404          elf_sym.st_name = sizeof(rgp_elf_strtab) + rt_name_offset;
405          rt_name_offset += strlen(record->shader_data[i].rt_shader_name) + 1;
406       } else
407          elf_sym.st_name = rgp_elf_hw_stage_string_offset[record->shader_data[i].hw_stage];
408       elf_sym.st_info = STT_FUNC;
409       elf_sym.st_other = 0x0;
410       elf_sym.st_shndx = RGP_ELF_TEXT_SEC_HEADER_INDEX;
411       elf_sym.st_value = record->shader_data[i].elf_symbol_offset;
412       elf_sym.st_size = record->shader_data[i].code_size;
413       fwrite(&elf_sym, 1, sizeof(elf_sym), output);
414    }
415 
416    *symbol_table_size = (record->num_shaders_combined + 1)
417                         * sizeof(elf_sym);
418    *elf_size_calc += *symbol_table_size;
419 }
420 
421 
422 /* Below defines from from llvm project
423  * llvm/includel/llvm/BinaryFormat/ELF.h
424  */
425 #define ELFOSABI_AMDGPU_PAL 65
426 #define NT_AMDGPU_METADATA 32
427 
428 uint8_t elf_ident[EI_NIDENT] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
429                                  ELFCLASS64, ELFDATA2LSB, EV_CURRENT,
430                                  ELFOSABI_AMDGPU_PAL,
431                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
432                                  0x00, 0x00 };
433 
434 #define NOTE_MSGPACK_NAME "AMDGPU"
435 struct ac_rgp_elf_note_msgpack_hdr {
436    Elf64_Nhdr  hdr;
437    char name[sizeof(NOTE_MSGPACK_NAME)];
438 };
439 
440 void
ac_rgp_file_write_elf_object(FILE * output,size_t file_elf_start,struct rgp_code_object_record * record,uint32_t * written_size,uint32_t flags)441 ac_rgp_file_write_elf_object(FILE *output, size_t file_elf_start,
442                              struct rgp_code_object_record *record,
443                              uint32_t *written_size, uint32_t flags)
444 {
445    Elf64_Ehdr elf_hdr;
446    Elf64_Shdr sec_hdr[5];
447    uint32_t elf_size_calc;
448    struct ac_rgp_elf_note_msgpack_hdr note_hdr;
449    uint32_t text_size = 0;
450    uint32_t symbol_table_size = 0;
451    uint32_t msgpack_size = 0;
452    size_t note_sec_start;
453    uint32_t sh_offset;
454    uint32_t strtab_size = sizeof(rgp_elf_strtab);
455 
456    /* Give space for header in file. It will be written to file at the end */
457    fseek(output, sizeof(Elf64_Ehdr), SEEK_CUR);
458 
459    elf_size_calc = sizeof(Elf64_Ehdr);
460 
461    /* Initialize elf header */
462    memcpy(&elf_hdr.e_ident, &elf_ident, EI_NIDENT);
463    elf_hdr.e_type = ET_REL;
464    elf_hdr.e_machine = EM_AMDGPU;
465    elf_hdr.e_version = EV_CURRENT;
466    elf_hdr.e_entry = 0;
467    elf_hdr.e_flags = flags;
468    elf_hdr.e_shstrndx = 1; /* string table entry is hardcoded to 1*/
469    elf_hdr.e_phoff = 0;
470    elf_hdr.e_shentsize = sizeof(Elf64_Shdr);
471    elf_hdr.e_ehsize = sizeof(Elf64_Ehdr);
472    elf_hdr.e_phentsize = 0;
473    elf_hdr.e_phnum = 0;
474 
475    /* write hardcoded string table */
476    fwrite(&rgp_elf_strtab, 1, sizeof(rgp_elf_strtab), output);
477    if (record->is_rt) {
478       uint32_t mask = record->shader_stages_mask;
479       while (mask) {
480          int i = u_bit_scan(&mask);
481 
482          char *name = record->shader_data[i].rt_shader_name;
483          uint32_t name_len = strlen(name);
484 
485          fwrite(name, 1, name_len + 1, output);
486          strtab_size += name_len + 1;
487       }
488    }
489    elf_size_calc += strtab_size;
490 
491    /* write shader code as .text code */
492    ac_rgp_file_write_elf_text(output, &elf_size_calc, record, &text_size);
493 
494    /* write symbol table */
495    ac_rgp_file_write_elf_symbol_table(output, &elf_size_calc, record,
496                                       &symbol_table_size);
497 
498    /* write .note */
499    /* the .note section contains msgpack which stores variables */
500    note_sec_start = file_elf_start + elf_size_calc;
501    fseek(output, sizeof(struct ac_rgp_elf_note_msgpack_hdr), SEEK_CUR);
502    ac_rgp_write_msgpack(output, record, &msgpack_size);
503    note_hdr.hdr.n_namesz = sizeof(NOTE_MSGPACK_NAME);
504    note_hdr.hdr.n_descsz = msgpack_size;
505    note_hdr.hdr.n_type = NT_AMDGPU_METADATA;
506    memcpy(note_hdr.name, NOTE_MSGPACK_NAME "\0",
507           sizeof(NOTE_MSGPACK_NAME) + 1);
508    fseek(output, note_sec_start, SEEK_SET);
509    fwrite(&note_hdr, 1, sizeof(struct ac_rgp_elf_note_msgpack_hdr), output);
510    fseek(output, 0, SEEK_END);
511    elf_size_calc += (msgpack_size +
512                      sizeof(struct ac_rgp_elf_note_msgpack_hdr));
513 
514    /* write section headers */
515    sh_offset = elf_size_calc;
516    memset(&sec_hdr[0], 0x00, sizeof(Elf64_Shdr) * 5);
517 
518    /* string table must be at index 1 as used in other places*/
519    sec_hdr[1].sh_name = (uintptr_t)((struct ac_rgp_elf_string_table*)0)->strtab;
520    sec_hdr[1].sh_type = SHT_STRTAB;
521    sec_hdr[1].sh_offset = sizeof(Elf64_Ehdr);
522    sec_hdr[1].sh_size = strtab_size;
523 
524    /* text must be at index 2 as used in other places*/
525    sec_hdr[2].sh_name = (uintptr_t)((struct ac_rgp_elf_string_table*)0)->text;
526    sec_hdr[2].sh_type = SHT_PROGBITS;
527    sec_hdr[2].sh_flags = SHF_ALLOC | SHF_EXECINSTR;
528    sec_hdr[2].sh_offset = sec_hdr[1].sh_offset + sec_hdr[1].sh_size;
529    sec_hdr[2].sh_size = text_size;
530    sec_hdr[2].sh_addralign = 256;
531 
532    sec_hdr[3].sh_name = (uintptr_t)((struct ac_rgp_elf_string_table*)0)->symtab;
533    sec_hdr[3].sh_type = SHT_SYMTAB;
534    sec_hdr[3].sh_offset = sec_hdr[2].sh_offset +
535                           align64(sec_hdr[2].sh_size, 256);
536    sec_hdr[3].sh_size = symbol_table_size;
537    sec_hdr[3].sh_link = RGP_ELF_STRING_TBL_SEC_HEADER_INDEX;
538    sec_hdr[3].sh_addralign = 8;
539    sec_hdr[3].sh_entsize = sizeof(Elf64_Sym);
540 
541    sec_hdr[4].sh_name = (uintptr_t)((struct ac_rgp_elf_string_table*)0)->note;
542    sec_hdr[4].sh_type = SHT_NOTE;
543    sec_hdr[4].sh_offset = sec_hdr[3].sh_offset + sec_hdr[3].sh_size;
544    sec_hdr[4].sh_size = msgpack_size +
545                         sizeof(struct ac_rgp_elf_note_msgpack_hdr);
546    sec_hdr[4].sh_addralign = 4;
547    fwrite(&sec_hdr, 1, sizeof(Elf64_Shdr) * 5, output);
548    elf_size_calc += (sizeof(Elf64_Shdr) * 5);
549 
550    /* update and write elf header */
551    elf_hdr.e_shnum = 5;
552    elf_hdr.e_shoff = sh_offset;
553 
554    fseek(output, file_elf_start, SEEK_SET);
555    fwrite(&elf_hdr, 1, sizeof(Elf64_Ehdr), output);
556    fseek(output, 0, SEEK_END);
557 
558    *written_size = elf_size_calc;
559 }
560