From 5505ee8904fafc7c1f017f88853f80a616784cf2 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Thu, 7 May 2020 09:49:27 +0200 Subject: misc: deprecate elftool Type: make Change-Id: I34fec1c40ef660177c266517eaf41d60827609f4 Signed-off-by: Damjan Marion --- .../developers/buildsystem/cmakeandninja.rst | 2 +- extras/deprecated/elftool/CMakeLists.txt | 17 + extras/deprecated/elftool/dir.dox | 19 + extras/deprecated/elftool/elftool.c | 464 +++++++++++++++++++++ extras/rpm/vpp-suse.spec | 1 - extras/rpm/vpp.spec | 1 - extras/selinux/vpp-custom.fc | 1 - src/CMakeLists.txt | 2 +- src/tools/elftool/CMakeLists.txt | 17 - src/tools/elftool/dir.dox | 19 - src/tools/elftool/elftool.c | 464 --------------------- 11 files changed, 502 insertions(+), 505 deletions(-) create mode 100644 extras/deprecated/elftool/CMakeLists.txt create mode 100644 extras/deprecated/elftool/dir.dox create mode 100644 extras/deprecated/elftool/elftool.c delete mode 100644 src/tools/elftool/CMakeLists.txt delete mode 100644 src/tools/elftool/dir.dox delete mode 100644 src/tools/elftool/elftool.c diff --git a/docs/gettingstarted/developers/buildsystem/cmakeandninja.rst b/docs/gettingstarted/developers/buildsystem/cmakeandninja.rst index b6d83f225ce..580d261bdac 100644 --- a/docs/gettingstarted/developers/buildsystem/cmakeandninja.rst +++ b/docs/gettingstarted/developers/buildsystem/cmakeandninja.rst @@ -34,7 +34,7 @@ of files: rule/function definitions, and target lists. find_package(OpenSSL REQUIRED) set(SUBDIRS vppinfra svm vlib vlibmemory vlibapi vnet vpp vat vcl plugins - vpp-api tools/vppapigen tools/g2 tools/elftool tools/perftool) + vpp-api tools/vppapigen tools/g2 tools/perftool) elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") set(SUBDIRS vppinfra) else() diff --git a/extras/deprecated/elftool/CMakeLists.txt b/extras/deprecated/elftool/CMakeLists.txt new file mode 100644 index 00000000000..d85c2b56c59 --- /dev/null +++ b/extras/deprecated/elftool/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (c) 2018 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +add_vpp_executable(elftool + SOURCES elftool.c + LINK_LIBRARIES vppinfra +) diff --git a/extras/deprecated/elftool/dir.dox b/extras/deprecated/elftool/dir.dox new file mode 100644 index 00000000000..40426e04df7 --- /dev/null +++ b/extras/deprecated/elftool/dir.dox @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * Copyright (c) 2016 Comcast Cable Communications Management, LLC. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** @dir + * @brief VPP instrastructure tools. + */ diff --git a/extras/deprecated/elftool/elftool.c b/extras/deprecated/elftool/elftool.c new file mode 100644 index 00000000000..e808c619da8 --- /dev/null +++ b/extras/deprecated/elftool/elftool.c @@ -0,0 +1,464 @@ +/* + * Copyright (c) 2015 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + Copyright (c) 2008 Eliot Dresselhaus + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include +#include +#include + +#ifndef CLIB_UNIX +#error "unix only" +#endif + +typedef struct { + elf_main_t elf_main; + char * input_file; + char * output_file; + char * set_interpreter; + char * set_rpath; + int unset_rpath; + int verbose; + int quiet; + int allow_elf_shared; + /* for use in the optimized / simplified case */ + u64 file_size; + u64 interpreter_offset; + u64 rpath_offset; +} elf_tool_main_t; + +static clib_error_t * elf_set_interpreter (elf_main_t * em, + elf_tool_main_t * tm) +{ + elf_segment_t * g; + elf_section_t * s; + clib_error_t * error; + char * interp = tm->set_interpreter; + + switch (em->first_header.file_type) + { + case ELF_EXEC: + break; + + case ELF_SHARED: + if (tm->allow_elf_shared) + break; + /* Note flowthrough */ + default: + return clib_error_return (0, "unacceptable file_type"); + } + + vec_foreach (g, em->segments) + { + if (g->header.type == ELF_SEGMENT_INTERP) + break; + } + + if (g >= vec_end (em->segments)) + return clib_error_return (0, "interpreter not found"); + + if (g->header.memory_size < 1 + strlen (interp)) + return clib_error_return (0, "given interpreter does not fit; must be less than %d bytes (`%s' given)", + g->header.memory_size, interp); + + error = elf_get_section_by_start_address (em, g->header.virtual_address, &s); + if (error) + return error; + + /* Put in new null terminated string. */ + clib_memset (s->contents, 0, vec_len (s->contents)); + clib_memcpy (s->contents, interp, strlen (interp)); + + return 0; +} + +static void +delete_rpath_for_section (elf_main_t * em, elf_section_t * s) +{ + elf64_dynamic_entry_t * e; + elf64_dynamic_entry_t * new_es = 0; + + vec_foreach (e, em->dynamic_entries) + { + switch (e->type) + { + case ELF_DYNAMIC_ENTRY_RPATH: + case ELF_DYNAMIC_ENTRY_RUN_PATH: + break; + + default: + vec_add1 (new_es, e[0]); + break; + } + } + + /* Pad so as to keep section size constant. */ + { + elf64_dynamic_entry_t e_end; + e_end.type = ELF_DYNAMIC_ENTRY_END; + e_end.data = 0; + while (vec_len (new_es) < vec_len (em->dynamic_entries)) + vec_add1 (new_es, e_end); + } + + vec_free (em->dynamic_entries); + em->dynamic_entries = new_es; + + elf_set_dynamic_entries (em); +} + +static void delete_rpath (elf_main_t * em) +{ + elf_section_t * s; + + vec_foreach (s, em->sections) + { + switch (s->header.type) + { + case ELF_SECTION_DYNAMIC: + delete_rpath_for_section (em, s); + break; + + default: + break; + } + } +} + +static clib_error_t * +set_rpath_for_section (elf_main_t * em, elf_section_t * s, char * new_rpath) +{ + elf64_dynamic_entry_t * e; + char * old_rpath; + int old_len, new_len = strlen (new_rpath); + u8 * new_string_table = vec_dup (em->dynamic_string_table); + + vec_foreach (e, em->dynamic_entries) + { + switch (e->type) + { + case ELF_DYNAMIC_ENTRY_RPATH: + case ELF_DYNAMIC_ENTRY_RUN_PATH: + old_rpath = (char *) new_string_table + e->data; + old_len = strlen (old_rpath); + if (old_len < new_len) + return clib_error_return (0, "rpath of `%s' does not fit (old rpath `%s')", + new_rpath, old_rpath); + strcpy (old_rpath, new_rpath); //NOSONAR + break; + + default: + break; + } + } + + elf_set_section_contents (em, em->dynamic_string_table_section_index, + new_string_table, + vec_bytes (new_string_table)); + + return 0; +} + +static clib_error_t * +set_rpath (elf_main_t * em, char * rpath) +{ + clib_error_t * error = 0; + elf_section_t * s; + + vec_foreach (s, em->sections) + { + switch (s->header.type) + { + case ELF_SECTION_DYNAMIC: + error = set_rpath_for_section (em, s, rpath); + if (error) + return error; + break; + + default: + break; + } + } + + return error; +} + +static clib_error_t * +set_interpreter_rpath (elf_tool_main_t * tm) +{ + int ifd = -1, ofd = -1; + struct stat fd_stat; + u8 *idp = 0; /* warning be gone */ + u64 mmap_length = 0, i; + u32 run_length; + u8 in_run; + u64 offset0 = 0, offset1 = 0; + clib_error_t * error = 0; + int fix_in_place = 0; + + if (!strcmp (tm->input_file, tm->output_file)) + fix_in_place = 1; + + ifd = open (tm->input_file, O_RDWR); + if (ifd < 0) + { + error = clib_error_return_unix (0, "open `%s'", tm->input_file); + goto done; + } + + if (fstat (ifd, &fd_stat) < 0) + { + error = clib_error_return_unix (0, "fstat `%s'", tm->input_file); + goto done; + } + + if (!(fd_stat.st_mode & S_IFREG)) + { + error = clib_error_return (0, "%s is not a regular file", tm->input_file); + goto done; + } + + mmap_length = fd_stat.st_size; + if (mmap_length < 4) + { + error = clib_error_return (0, "%s too short", tm->input_file); + goto done; + } + + /* COW-mapping, since we intend to write the fixups */ + if (fix_in_place) + idp = mmap (0, mmap_length, PROT_READ | PROT_WRITE, MAP_SHARED, + ifd, /* offset */ 0); + else + idp = mmap (0, mmap_length, PROT_READ | PROT_WRITE, MAP_PRIVATE, + ifd, /* offset */ 0); + if (~pointer_to_uword (idp) == 0) + { + mmap_length = 0; + error = clib_error_return_unix (0, "mmap `%s'", tm->input_file); + goto done; + } + + if (idp[0] != 0x7f || idp[1] != 'E' || idp[2] != 'L' || idp[3] != 'F') + { + error = clib_error_return (0, "not an ELF file '%s'", tm->input_file); + goto done; + } + + in_run = 0; + run_length = 0; + + for (i = 0; i < mmap_length; i++) + { + if (idp[i] == '/') + { + if (in_run) + run_length++; + else + { + in_run = 1; + run_length = 1; + } + } + else + { + if (in_run && run_length >= 16) + { + if (offset0 == 0) + offset0 = (i - run_length); + else if (offset1 == 0) + { + offset1 = (i - run_length); + goto found_both; + } + } + in_run = 0; + run_length = 0; + } + } + + if (offset0 == 0) + { + error = clib_error_return (0, "no fixup markers in %s", + tm->input_file); + goto done; + } + + found_both: + if (0) + clib_warning ("offset0 %lld (0x%llx), offset1 %lld (0x%llx)", + offset0, offset0, offset1, offset1); + + /* Executable file case */ + if (offset0 && offset1) + { + tm->interpreter_offset = offset0; + tm->rpath_offset = offset1; + } + else /* shared library case */ + { + tm->interpreter_offset = 0; + tm->rpath_offset = offset0; + } + + if (tm->interpreter_offset) + clib_memcpy (&idp[tm->interpreter_offset], tm->set_interpreter, + strlen (tm->set_interpreter)+1); + + if (tm->rpath_offset) + clib_memcpy (&idp[tm->rpath_offset], tm->set_rpath, + strlen (tm->set_rpath)+1); + + /* Write the output file... */ + if (fix_in_place == 0) + { + ofd = open (tm->output_file, O_RDWR | O_CREAT | O_TRUNC, 0644); + if (ofd < 0) + { + error = clib_error_return_unix (0, "create `%s'", tm->output_file); + goto done; + } + + if (write (ofd, idp, mmap_length) != mmap_length) + error = clib_error_return_unix (0, "write `%s'", tm->output_file); + } + + done: + if (mmap_length > 0 && idp) + munmap (idp, mmap_length); + if (ifd >= 0) + close (ifd); + if (ofd >= 0) + close (ofd); + return error; +} + + +int main (int argc, char * argv[]) +{ + elf_tool_main_t _tm, * tm = &_tm; + elf_main_t * em = &tm->elf_main; + unformat_input_t i; + clib_error_t * error = 0; + + clib_memset (tm, 0, sizeof (tm[0])); + unformat_init_command_line (&i, argv); + + while (unformat_check_input (&i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (&i, "in %s", &tm->input_file)) + ; + else if (unformat (&i, "out %s", &tm->output_file)) + ; + else if (unformat (&i, "set-interpreter %s", &tm->set_interpreter)) + ; + else if (unformat (&i, "set-rpath %s", &tm->set_rpath)) + ; + else if (unformat (&i, "unset-rpath")) + tm->unset_rpath = 1; + else if (unformat (&i, "verbose")) + tm->verbose = ~0; + else if (unformat (&i, "verbose-symbols")) + tm->verbose |= FORMAT_ELF_MAIN_SYMBOLS; + else if (unformat (&i, "verbose-relocations")) + tm->verbose |= FORMAT_ELF_MAIN_RELOCATIONS; + else if (unformat (&i, "verbose-dynamic")) + tm->verbose |= FORMAT_ELF_MAIN_DYNAMIC; + else if (unformat (&i, "quiet")) + tm->quiet = 1; + else if (unformat (&i, "allow-elf-shared")) + tm->allow_elf_shared = 1; + else + { + error = unformat_parse_error (&i); + goto done; + } + } + + if (! tm->input_file) + { + error = clib_error_return (0, "no input file"); + goto done; + } + + /* Do the typical case a stone-simple way... */ + if (tm->quiet && tm->set_interpreter && tm->set_rpath && tm->output_file) + { + error = set_interpreter_rpath (tm); + goto done; + } + + error = elf_read_file (em, tm->input_file); + + if (error) + goto done; + + if (tm->verbose) + fformat (stdout, "%U", format_elf_main, em, tm->verbose); + + if (tm->set_interpreter) + { + error = elf_set_interpreter (em, tm); + if (error) + goto done; + } + + if (tm->set_rpath) + { + error = set_rpath (em, tm->set_rpath); + if (error) + goto done; + } + + if (tm->unset_rpath) + delete_rpath (em); + + if (tm->output_file) + error = elf_write_file (em, tm->output_file); + + elf_main_free (em); + + done: + if (error) + { + if (tm->quiet == 0) + clib_error_report (error); + return 1; + } + else + return 0; +} diff --git a/extras/rpm/vpp-suse.spec b/extras/rpm/vpp-suse.spec index 042e17a0b49..4bb354cda90 100644 --- a/extras/rpm/vpp-suse.spec +++ b/extras/rpm/vpp-suse.spec @@ -289,7 +289,6 @@ export NO_BRP_CHECK_RPATH=true %{_unitdir}/vpp.service %{_bindir}/vpp* %{_bindir}/svm* -%{_bindir}/elftool %dir %{_sysconfdir}/vpp %config %{_sysconfdir}/sysctl.d/80-vpp.conf %config %{_sysconfdir}/vpp/startup.conf diff --git a/extras/rpm/vpp.spec b/extras/rpm/vpp.spec index f2de430d670..538c071caea 100644 --- a/extras/rpm/vpp.spec +++ b/extras/rpm/vpp.spec @@ -375,7 +375,6 @@ fi %{_unitdir}/vpp.service /usr/bin/vpp* /usr/bin/svm* -/usr/bin/elftool %config(noreplace) /etc/sysctl.d/80-vpp.conf %config(noreplace) /etc/vpp/startup.conf /usr/share/vpp/api/* diff --git a/extras/selinux/vpp-custom.fc b/extras/selinux/vpp-custom.fc index 4b4428e7150..166166e7f6e 100644 --- a/extras/selinux/vpp-custom.fc +++ b/extras/selinux/vpp-custom.fc @@ -1,6 +1,5 @@ /etc/vpp(/.*)? gen_context(system_u:object_r:vpp_config_rw_t,s0) -/usr/bin/elftool -- gen_context(system_u:object_r:vpp_exec_t,s0) /usr/bin/svmdbtool -- gen_context(system_u:object_r:vpp_exec_t,s0) /usr/bin/svmtool -- gen_context(system_u:object_r:vpp_exec_t,s0) /usr/bin/vpp -- gen_context(system_u:object_r:vpp_exec_t,s0) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1564fd0ad8c..2e3cf6b1d68 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -143,7 +143,7 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") find_package(OpenSSL REQUIRED) set(SUBDIRS vppinfra svm vlib vlibmemory vlibapi vnet vpp vat vcl plugins - vpp-api tools/vppapigen tools/g2 tools/elftool tools/perftool cmake pkg + vpp-api tools/vppapigen tools/g2 tools/perftool cmake pkg tools/appimage ) elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") diff --git a/src/tools/elftool/CMakeLists.txt b/src/tools/elftool/CMakeLists.txt deleted file mode 100644 index d85c2b56c59..00000000000 --- a/src/tools/elftool/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2018 Cisco and/or its affiliates. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -add_vpp_executable(elftool - SOURCES elftool.c - LINK_LIBRARIES vppinfra -) diff --git a/src/tools/elftool/dir.dox b/src/tools/elftool/dir.dox deleted file mode 100644 index 40426e04df7..00000000000 --- a/src/tools/elftool/dir.dox +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Copyright (c) 2016 Comcast Cable Communications Management, LLC. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** @dir - * @brief VPP instrastructure tools. - */ diff --git a/src/tools/elftool/elftool.c b/src/tools/elftool/elftool.c deleted file mode 100644 index e808c619da8..00000000000 --- a/src/tools/elftool/elftool.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2008 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include - -#include -#include -#include - -#ifndef CLIB_UNIX -#error "unix only" -#endif - -typedef struct { - elf_main_t elf_main; - char * input_file; - char * output_file; - char * set_interpreter; - char * set_rpath; - int unset_rpath; - int verbose; - int quiet; - int allow_elf_shared; - /* for use in the optimized / simplified case */ - u64 file_size; - u64 interpreter_offset; - u64 rpath_offset; -} elf_tool_main_t; - -static clib_error_t * elf_set_interpreter (elf_main_t * em, - elf_tool_main_t * tm) -{ - elf_segment_t * g; - elf_section_t * s; - clib_error_t * error; - char * interp = tm->set_interpreter; - - switch (em->first_header.file_type) - { - case ELF_EXEC: - break; - - case ELF_SHARED: - if (tm->allow_elf_shared) - break; - /* Note flowthrough */ - default: - return clib_error_return (0, "unacceptable file_type"); - } - - vec_foreach (g, em->segments) - { - if (g->header.type == ELF_SEGMENT_INTERP) - break; - } - - if (g >= vec_end (em->segments)) - return clib_error_return (0, "interpreter not found"); - - if (g->header.memory_size < 1 + strlen (interp)) - return clib_error_return (0, "given interpreter does not fit; must be less than %d bytes (`%s' given)", - g->header.memory_size, interp); - - error = elf_get_section_by_start_address (em, g->header.virtual_address, &s); - if (error) - return error; - - /* Put in new null terminated string. */ - clib_memset (s->contents, 0, vec_len (s->contents)); - clib_memcpy (s->contents, interp, strlen (interp)); - - return 0; -} - -static void -delete_rpath_for_section (elf_main_t * em, elf_section_t * s) -{ - elf64_dynamic_entry_t * e; - elf64_dynamic_entry_t * new_es = 0; - - vec_foreach (e, em->dynamic_entries) - { - switch (e->type) - { - case ELF_DYNAMIC_ENTRY_RPATH: - case ELF_DYNAMIC_ENTRY_RUN_PATH: - break; - - default: - vec_add1 (new_es, e[0]); - break; - } - } - - /* Pad so as to keep section size constant. */ - { - elf64_dynamic_entry_t e_end; - e_end.type = ELF_DYNAMIC_ENTRY_END; - e_end.data = 0; - while (vec_len (new_es) < vec_len (em->dynamic_entries)) - vec_add1 (new_es, e_end); - } - - vec_free (em->dynamic_entries); - em->dynamic_entries = new_es; - - elf_set_dynamic_entries (em); -} - -static void delete_rpath (elf_main_t * em) -{ - elf_section_t * s; - - vec_foreach (s, em->sections) - { - switch (s->header.type) - { - case ELF_SECTION_DYNAMIC: - delete_rpath_for_section (em, s); - break; - - default: - break; - } - } -} - -static clib_error_t * -set_rpath_for_section (elf_main_t * em, elf_section_t * s, char * new_rpath) -{ - elf64_dynamic_entry_t * e; - char * old_rpath; - int old_len, new_len = strlen (new_rpath); - u8 * new_string_table = vec_dup (em->dynamic_string_table); - - vec_foreach (e, em->dynamic_entries) - { - switch (e->type) - { - case ELF_DYNAMIC_ENTRY_RPATH: - case ELF_DYNAMIC_ENTRY_RUN_PATH: - old_rpath = (char *) new_string_table + e->data; - old_len = strlen (old_rpath); - if (old_len < new_len) - return clib_error_return (0, "rpath of `%s' does not fit (old rpath `%s')", - new_rpath, old_rpath); - strcpy (old_rpath, new_rpath); //NOSONAR - break; - - default: - break; - } - } - - elf_set_section_contents (em, em->dynamic_string_table_section_index, - new_string_table, - vec_bytes (new_string_table)); - - return 0; -} - -static clib_error_t * -set_rpath (elf_main_t * em, char * rpath) -{ - clib_error_t * error = 0; - elf_section_t * s; - - vec_foreach (s, em->sections) - { - switch (s->header.type) - { - case ELF_SECTION_DYNAMIC: - error = set_rpath_for_section (em, s, rpath); - if (error) - return error; - break; - - default: - break; - } - } - - return error; -} - -static clib_error_t * -set_interpreter_rpath (elf_tool_main_t * tm) -{ - int ifd = -1, ofd = -1; - struct stat fd_stat; - u8 *idp = 0; /* warning be gone */ - u64 mmap_length = 0, i; - u32 run_length; - u8 in_run; - u64 offset0 = 0, offset1 = 0; - clib_error_t * error = 0; - int fix_in_place = 0; - - if (!strcmp (tm->input_file, tm->output_file)) - fix_in_place = 1; - - ifd = open (tm->input_file, O_RDWR); - if (ifd < 0) - { - error = clib_error_return_unix (0, "open `%s'", tm->input_file); - goto done; - } - - if (fstat (ifd, &fd_stat) < 0) - { - error = clib_error_return_unix (0, "fstat `%s'", tm->input_file); - goto done; - } - - if (!(fd_stat.st_mode & S_IFREG)) - { - error = clib_error_return (0, "%s is not a regular file", tm->input_file); - goto done; - } - - mmap_length = fd_stat.st_size; - if (mmap_length < 4) - { - error = clib_error_return (0, "%s too short", tm->input_file); - goto done; - } - - /* COW-mapping, since we intend to write the fixups */ - if (fix_in_place) - idp = mmap (0, mmap_length, PROT_READ | PROT_WRITE, MAP_SHARED, - ifd, /* offset */ 0); - else - idp = mmap (0, mmap_length, PROT_READ | PROT_WRITE, MAP_PRIVATE, - ifd, /* offset */ 0); - if (~pointer_to_uword (idp) == 0) - { - mmap_length = 0; - error = clib_error_return_unix (0, "mmap `%s'", tm->input_file); - goto done; - } - - if (idp[0] != 0x7f || idp[1] != 'E' || idp[2] != 'L' || idp[3] != 'F') - { - error = clib_error_return (0, "not an ELF file '%s'", tm->input_file); - goto done; - } - - in_run = 0; - run_length = 0; - - for (i = 0; i < mmap_length; i++) - { - if (idp[i] == '/') - { - if (in_run) - run_length++; - else - { - in_run = 1; - run_length = 1; - } - } - else - { - if (in_run && run_length >= 16) - { - if (offset0 == 0) - offset0 = (i - run_length); - else if (offset1 == 0) - { - offset1 = (i - run_length); - goto found_both; - } - } - in_run = 0; - run_length = 0; - } - } - - if (offset0 == 0) - { - error = clib_error_return (0, "no fixup markers in %s", - tm->input_file); - goto done; - } - - found_both: - if (0) - clib_warning ("offset0 %lld (0x%llx), offset1 %lld (0x%llx)", - offset0, offset0, offset1, offset1); - - /* Executable file case */ - if (offset0 && offset1) - { - tm->interpreter_offset = offset0; - tm->rpath_offset = offset1; - } - else /* shared library case */ - { - tm->interpreter_offset = 0; - tm->rpath_offset = offset0; - } - - if (tm->interpreter_offset) - clib_memcpy (&idp[tm->interpreter_offset], tm->set_interpreter, - strlen (tm->set_interpreter)+1); - - if (tm->rpath_offset) - clib_memcpy (&idp[tm->rpath_offset], tm->set_rpath, - strlen (tm->set_rpath)+1); - - /* Write the output file... */ - if (fix_in_place == 0) - { - ofd = open (tm->output_file, O_RDWR | O_CREAT | O_TRUNC, 0644); - if (ofd < 0) - { - error = clib_error_return_unix (0, "create `%s'", tm->output_file); - goto done; - } - - if (write (ofd, idp, mmap_length) != mmap_length) - error = clib_error_return_unix (0, "write `%s'", tm->output_file); - } - - done: - if (mmap_length > 0 && idp) - munmap (idp, mmap_length); - if (ifd >= 0) - close (ifd); - if (ofd >= 0) - close (ofd); - return error; -} - - -int main (int argc, char * argv[]) -{ - elf_tool_main_t _tm, * tm = &_tm; - elf_main_t * em = &tm->elf_main; - unformat_input_t i; - clib_error_t * error = 0; - - clib_memset (tm, 0, sizeof (tm[0])); - unformat_init_command_line (&i, argv); - - while (unformat_check_input (&i) != UNFORMAT_END_OF_INPUT) - { - if (unformat (&i, "in %s", &tm->input_file)) - ; - else if (unformat (&i, "out %s", &tm->output_file)) - ; - else if (unformat (&i, "set-interpreter %s", &tm->set_interpreter)) - ; - else if (unformat (&i, "set-rpath %s", &tm->set_rpath)) - ; - else if (unformat (&i, "unset-rpath")) - tm->unset_rpath = 1; - else if (unformat (&i, "verbose")) - tm->verbose = ~0; - else if (unformat (&i, "verbose-symbols")) - tm->verbose |= FORMAT_ELF_MAIN_SYMBOLS; - else if (unformat (&i, "verbose-relocations")) - tm->verbose |= FORMAT_ELF_MAIN_RELOCATIONS; - else if (unformat (&i, "verbose-dynamic")) - tm->verbose |= FORMAT_ELF_MAIN_DYNAMIC; - else if (unformat (&i, "quiet")) - tm->quiet = 1; - else if (unformat (&i, "allow-elf-shared")) - tm->allow_elf_shared = 1; - else - { - error = unformat_parse_error (&i); - goto done; - } - } - - if (! tm->input_file) - { - error = clib_error_return (0, "no input file"); - goto done; - } - - /* Do the typical case a stone-simple way... */ - if (tm->quiet && tm->set_interpreter && tm->set_rpath && tm->output_file) - { - error = set_interpreter_rpath (tm); - goto done; - } - - error = elf_read_file (em, tm->input_file); - - if (error) - goto done; - - if (tm->verbose) - fformat (stdout, "%U", format_elf_main, em, tm->verbose); - - if (tm->set_interpreter) - { - error = elf_set_interpreter (em, tm); - if (error) - goto done; - } - - if (tm->set_rpath) - { - error = set_rpath (em, tm->set_rpath); - if (error) - goto done; - } - - if (tm->unset_rpath) - delete_rpath (em); - - if (tm->output_file) - error = elf_write_file (em, tm->output_file); - - elf_main_free (em); - - done: - if (error) - { - if (tm->quiet == 0) - clib_error_report (error); - return 1; - } - else - return 0; -} -- cgit 1.2.3-korg