OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Implementation notes: | 5 // Implementation notes: |
6 // | 6 // |
7 // We need to remove a piece from the ELF shared library. However, we also | 7 // We need to remove a piece from the ELF shared library. However, we also |
8 // want to ensure that code and data loads at the same addresses as before | 8 // want to ensure that code and data loads at the same addresses as before |
9 // packing, so that tools like breakpad can still match up addresses found | 9 // packing, so that tools like breakpad can still match up addresses found |
10 // in any crash dumps with data extracted from the pre-packed version of | 10 // in any crash dumps with data extracted from the pre-packed version of |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 // by ensuring that a call to elf_getdata(section, data) returns NULL as | 64 // by ensuring that a call to elf_getdata(section, data) returns NULL as |
65 // the next data entry. | 65 // the next data entry. |
66 Elf_Data* GetSectionData(Elf_Scn* section) { | 66 Elf_Data* GetSectionData(Elf_Scn* section) { |
67 Elf_Data* data = elf_getdata(section, NULL); | 67 Elf_Data* data = elf_getdata(section, NULL); |
68 CHECK(data && elf_getdata(section, data) == NULL); | 68 CHECK(data && elf_getdata(section, data) == NULL); |
69 return data; | 69 return data; |
70 } | 70 } |
71 | 71 |
72 // Rewrite section data. Allocates new data and makes it the data element's | 72 // Rewrite section data. Allocates new data and makes it the data element's |
73 // buffer. Relies on program exit to free allocated data. | 73 // buffer. Relies on program exit to free allocated data. |
74 void RewriteSectionData(Elf_Data* data, | 74 void RewriteSectionData(Elf_Scn* section, |
75 const void* section_data, | 75 const void* section_data, |
76 size_t size) { | 76 size_t size) { |
| 77 Elf_Data* data = GetSectionData(section); |
77 CHECK(size == data->d_size); | 78 CHECK(size == data->d_size); |
78 uint8_t* area = new uint8_t[size]; | 79 uint8_t* area = new uint8_t[size]; |
79 memcpy(area, section_data, size); | 80 memcpy(area, section_data, size); |
80 data->d_buf = area; | 81 data->d_buf = area; |
81 } | 82 } |
82 | 83 |
83 // Verbose ELF header logging. | 84 // Verbose ELF header logging. |
84 void VerboseLogElfHeader(const ELF::Ehdr* elf_header) { | 85 void VerboseLogElfHeader(const ELF::Ehdr* elf_header) { |
85 VLOG(1) << "e_phoff = " << elf_header->e_phoff; | 86 VLOG(1) << "e_phoff = " << elf_header->e_phoff; |
86 VLOG(1) << "e_shoff = " << elf_header->e_shoff; | 87 VLOG(1) << "e_shoff = " << elf_header->e_shoff; |
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
790 | 791 |
791 // DT_RELENT and DT_RELAENT do not change, but make sure they are what | 792 // DT_RELENT and DT_RELAENT do not change, but make sure they are what |
792 // we expect. Only one will be present. | 793 // we expect. Only one will be present. |
793 if (tag == DT_RELENT || tag == DT_RELAENT) { | 794 if (tag == DT_RELENT || tag == DT_RELAENT) { |
794 CHECK(dynamic->d_un.d_val == sizeof(Rel)); | 795 CHECK(dynamic->d_un.d_val == sizeof(Rel)); |
795 } | 796 } |
796 } | 797 } |
797 | 798 |
798 void* section_data = &dynamics[0]; | 799 void* section_data = &dynamics[0]; |
799 size_t bytes = dynamics.size() * sizeof(dynamics[0]); | 800 size_t bytes = dynamics.size() * sizeof(dynamics[0]); |
800 RewriteSectionData(data, section_data, bytes); | 801 RewriteSectionData(dynamic_section, section_data, bytes); |
801 } | 802 } |
802 | 803 |
803 // Resize a section. If the new size is larger than the current size, open | 804 // Resize a section. If the new size is larger than the current size, open |
804 // up a hole by increasing file offsets that come after the hole. If smaller | 805 // up a hole by increasing file offsets that come after the hole. If smaller |
805 // than the current size, remove the hole by decreasing those offsets. | 806 // than the current size, remove the hole by decreasing those offsets. |
806 template <typename Rel> | 807 template <typename Rel> |
807 void ResizeSection(Elf* elf, Elf_Scn* section, size_t new_size) { | 808 void ResizeSection(Elf* elf, Elf_Scn* section, size_t new_size) { |
808 ELF::Shdr* section_header = ELF::getshdr(section); | 809 ELF::Shdr* section_header = ELF::getshdr(section); |
809 if (section_header->sh_size == new_size) | 810 if (section_header->sh_size == new_size) |
810 return; | 811 return; |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
945 Elf_Data* data = GetSectionData(relocations_section_); | 946 Elf_Data* data = GetSectionData(relocations_section_); |
946 | 947 |
947 if (relocations_type_ == REL) { | 948 if (relocations_type_ == REL) { |
948 // Convert data to a vector of relocations. | 949 // Convert data to a vector of relocations. |
949 const ELF::Rel* relocations_base = reinterpret_cast<ELF::Rel*>(data->d_buf); | 950 const ELF::Rel* relocations_base = reinterpret_cast<ELF::Rel*>(data->d_buf); |
950 std::vector<ELF::Rel> relocations( | 951 std::vector<ELF::Rel> relocations( |
951 relocations_base, | 952 relocations_base, |
952 relocations_base + data->d_size / sizeof(relocations[0])); | 953 relocations_base + data->d_size / sizeof(relocations[0])); |
953 | 954 |
954 LOG(INFO) << "Relocations : REL"; | 955 LOG(INFO) << "Relocations : REL"; |
955 return PackTypedRelocations<ELF::Rel>(relocations, data); | 956 return PackTypedRelocations<ELF::Rel>(relocations); |
956 } | 957 } |
957 | 958 |
958 if (relocations_type_ == RELA) { | 959 if (relocations_type_ == RELA) { |
959 // Convert data to a vector of relocations with addends. | 960 // Convert data to a vector of relocations with addends. |
960 const ELF::Rela* relocations_base = | 961 const ELF::Rela* relocations_base = |
961 reinterpret_cast<ELF::Rela*>(data->d_buf); | 962 reinterpret_cast<ELF::Rela*>(data->d_buf); |
962 std::vector<ELF::Rela> relocations( | 963 std::vector<ELF::Rela> relocations( |
963 relocations_base, | 964 relocations_base, |
964 relocations_base + data->d_size / sizeof(relocations[0])); | 965 relocations_base + data->d_size / sizeof(relocations[0])); |
965 | 966 |
966 LOG(INFO) << "Relocations : RELA"; | 967 LOG(INFO) << "Relocations : RELA"; |
967 return PackTypedRelocations<ELF::Rela>(relocations, data); | 968 return PackTypedRelocations<ELF::Rela>(relocations); |
968 } | 969 } |
969 | 970 |
970 NOTREACHED(); | 971 NOTREACHED(); |
971 return false; | 972 return false; |
972 } | 973 } |
973 | 974 |
974 // Helper for PackRelocations(). Rel type is one of ELF::Rel or ELF::Rela. | 975 // Helper for PackRelocations(). Rel type is one of ELF::Rel or ELF::Rela. |
975 template <typename Rel> | 976 template <typename Rel> |
976 bool ElfFile::PackTypedRelocations(const std::vector<Rel>& relocations, | 977 bool ElfFile::PackTypedRelocations(const std::vector<Rel>& relocations) { |
977 Elf_Data* data) { | |
978 // Filter relocations into those that are relative and others. | 978 // Filter relocations into those that are relative and others. |
979 std::vector<Rel> relative_relocations; | 979 std::vector<Rel> relative_relocations; |
980 std::vector<Rel> other_relocations; | 980 std::vector<Rel> other_relocations; |
981 | 981 |
982 for (size_t i = 0; i < relocations.size(); ++i) { | 982 for (size_t i = 0; i < relocations.size(); ++i) { |
983 const Rel& relocation = relocations[i]; | 983 const Rel& relocation = relocations[i]; |
984 if (ELF_R_TYPE(relocation.r_info) == ELF::kRelativeRelocationCode) { | 984 if (ELF_R_TYPE(relocation.r_info) == ELF::kRelativeRelocationCode) { |
985 CHECK(ELF_R_SYM(relocation.r_info) == 0); | 985 CHECK(ELF_R_SYM(relocation.r_info) == 0); |
986 relative_relocations.push_back(relocation); | 986 relative_relocations.push_back(relocation); |
987 } else { | 987 } else { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1078 if (packed_bytes >= initial_bytes) { | 1078 if (packed_bytes >= initial_bytes) { |
1079 LOG(INFO) << "Packing relative relocations saves no space"; | 1079 LOG(INFO) << "Packing relative relocations saves no space"; |
1080 return false; | 1080 return false; |
1081 } | 1081 } |
1082 | 1082 |
1083 // Rewrite the current dynamic relocations section to be only the ARM | 1083 // Rewrite the current dynamic relocations section to be only the ARM |
1084 // non-relative relocations, then shrink it to size. | 1084 // non-relative relocations, then shrink it to size. |
1085 const void* section_data = &other_relocations[0]; | 1085 const void* section_data = &other_relocations[0]; |
1086 const size_t bytes = other_relocations.size() * sizeof(other_relocations[0]); | 1086 const size_t bytes = other_relocations.size() * sizeof(other_relocations[0]); |
1087 ResizeSection<Rel>(elf_, relocations_section_, bytes); | 1087 ResizeSection<Rel>(elf_, relocations_section_, bytes); |
1088 RewriteSectionData(data, section_data, bytes); | 1088 RewriteSectionData(relocations_section_, section_data, bytes); |
1089 | 1089 |
1090 // Rewrite the current packed android relocations section to hold the packed | 1090 // Rewrite the current packed android relocations section to hold the packed |
1091 // relative relocations. | 1091 // relative relocations. |
1092 data = GetSectionData(android_relocations_section_); | |
1093 ResizeSection<Rel>(elf_, android_relocations_section_, packed_bytes); | 1092 ResizeSection<Rel>(elf_, android_relocations_section_, packed_bytes); |
1094 RewriteSectionData(data, packed_data, packed_bytes); | 1093 RewriteSectionData(android_relocations_section_, packed_data, packed_bytes); |
1095 | 1094 |
1096 // Rewrite .dynamic to include two new tags describing the packed android | 1095 // Rewrite .dynamic to include two new tags describing the packed android |
1097 // relocations. | 1096 // relocations. |
1098 data = GetSectionData(dynamic_section_); | 1097 Elf_Data* data = GetSectionData(dynamic_section_); |
1099 const ELF::Dyn* dynamic_base = reinterpret_cast<ELF::Dyn*>(data->d_buf); | 1098 const ELF::Dyn* dynamic_base = reinterpret_cast<ELF::Dyn*>(data->d_buf); |
1100 std::vector<ELF::Dyn> dynamics( | 1099 std::vector<ELF::Dyn> dynamics( |
1101 dynamic_base, | 1100 dynamic_base, |
1102 dynamic_base + data->d_size / sizeof(dynamics[0])); | 1101 dynamic_base + data->d_size / sizeof(dynamics[0])); |
1103 // Use two of the spare slots to describe the packed section. | 1102 // Use two of the spare slots to describe the packed section. |
1104 ELF::Shdr* section_header = ELF::getshdr(android_relocations_section_); | 1103 ELF::Shdr* section_header = ELF::getshdr(android_relocations_section_); |
1105 { | 1104 { |
1106 ELF::Dyn dyn; | 1105 ELF::Dyn dyn; |
1107 dyn.d_tag = DT_ANDROID_REL_OFFSET; | 1106 dyn.d_tag = DT_ANDROID_REL_OFFSET; |
1108 dyn.d_un.d_ptr = section_header->sh_offset; | 1107 dyn.d_un.d_ptr = section_header->sh_offset; |
1109 AddDynamicEntry(dyn, &dynamics); | 1108 AddDynamicEntry(dyn, &dynamics); |
1110 } | 1109 } |
1111 { | 1110 { |
1112 ELF::Dyn dyn; | 1111 ELF::Dyn dyn; |
1113 dyn.d_tag = DT_ANDROID_REL_SIZE; | 1112 dyn.d_tag = DT_ANDROID_REL_SIZE; |
1114 dyn.d_un.d_val = section_header->sh_size; | 1113 dyn.d_un.d_val = section_header->sh_size; |
1115 AddDynamicEntry(dyn, &dynamics); | 1114 AddDynamicEntry(dyn, &dynamics); |
1116 } | 1115 } |
1117 const void* dynamics_data = &dynamics[0]; | 1116 const void* dynamics_data = &dynamics[0]; |
1118 const size_t dynamics_bytes = dynamics.size() * sizeof(dynamics[0]); | 1117 const size_t dynamics_bytes = dynamics.size() * sizeof(dynamics[0]); |
1119 RewriteSectionData(data, dynamics_data, dynamics_bytes); | 1118 RewriteSectionData(dynamic_section_, dynamics_data, dynamics_bytes); |
1120 | 1119 |
1121 Flush(); | 1120 Flush(); |
1122 return true; | 1121 return true; |
1123 } | 1122 } |
1124 | 1123 |
1125 // Find packed relative relocations in the packed android relocations | 1124 // Find packed relative relocations in the packed android relocations |
1126 // section, unpack them, and rewrite the dynamic relocations section to | 1125 // section, unpack them, and rewrite the dynamic relocations section to |
1127 // contain unpacked data. | 1126 // contain unpacked data. |
1128 bool ElfFile::UnpackRelocations() { | 1127 bool ElfFile::UnpackRelocations() { |
1129 // Load the ELF file into libelf. | 1128 // Load the ELF file into libelf. |
(...skipping 12 matching lines...) Expand all Loading... |
1142 packed_base + data->d_size / sizeof(packed[0])); | 1141 packed_base + data->d_size / sizeof(packed[0])); |
1143 | 1142 |
1144 if (packed.size() > 3 && | 1143 if (packed.size() > 3 && |
1145 packed[0] == 'A' && | 1144 packed[0] == 'A' && |
1146 packed[1] == 'P' && | 1145 packed[1] == 'P' && |
1147 packed[2] == 'R' && | 1146 packed[2] == 'R' && |
1148 packed[3] == '1') { | 1147 packed[3] == '1') { |
1149 // Signature is APR1, unpack relocations. | 1148 // Signature is APR1, unpack relocations. |
1150 CHECK(relocations_type_ == REL); | 1149 CHECK(relocations_type_ == REL); |
1151 LOG(INFO) << "Relocations : REL"; | 1150 LOG(INFO) << "Relocations : REL"; |
1152 return UnpackTypedRelocations<ELF::Rel>(packed, data); | 1151 return UnpackTypedRelocations<ELF::Rel>(packed); |
1153 } | 1152 } |
1154 | 1153 |
1155 if (packed.size() > 3 && | 1154 if (packed.size() > 3 && |
1156 packed[0] == 'A' && | 1155 packed[0] == 'A' && |
1157 packed[1] == 'P' && | 1156 packed[1] == 'P' && |
1158 packed[2] == 'A' && | 1157 packed[2] == 'A' && |
1159 packed[3] == '1') { | 1158 packed[3] == '1') { |
1160 // Signature is APA1, unpack relocations with addends. | 1159 // Signature is APA1, unpack relocations with addends. |
1161 CHECK(relocations_type_ == RELA); | 1160 CHECK(relocations_type_ == RELA); |
1162 LOG(INFO) << "Relocations : RELA"; | 1161 LOG(INFO) << "Relocations : RELA"; |
1163 return UnpackTypedRelocations<ELF::Rela>(packed, data); | 1162 return UnpackTypedRelocations<ELF::Rela>(packed); |
1164 } | 1163 } |
1165 | 1164 |
1166 LOG(ERROR) << "Packed relative relocations not found (not packed?)"; | 1165 LOG(ERROR) << "Packed relative relocations not found (not packed?)"; |
1167 return false; | 1166 return false; |
1168 } | 1167 } |
1169 | 1168 |
1170 // Helper for UnpackRelocations(). Rel type is one of ELF::Rel or ELF::Rela. | 1169 // Helper for UnpackRelocations(). Rel type is one of ELF::Rel or ELF::Rela. |
1171 template <typename Rel> | 1170 template <typename Rel> |
1172 bool ElfFile::UnpackTypedRelocations(const std::vector<uint8_t>& packed, | 1171 bool ElfFile::UnpackTypedRelocations(const std::vector<uint8_t>& packed) { |
1173 Elf_Data* data) { | |
1174 // Unpack the data to re-materialize the relative relocations. | 1172 // Unpack the data to re-materialize the relative relocations. |
1175 const size_t packed_bytes = packed.size() * sizeof(packed[0]); | 1173 const size_t packed_bytes = packed.size() * sizeof(packed[0]); |
1176 LOG(INFO) << "Packed relative: " << packed_bytes << " bytes"; | 1174 LOG(INFO) << "Packed relative: " << packed_bytes << " bytes"; |
1177 std::vector<Rel> relative_relocations; | 1175 std::vector<Rel> relative_relocations; |
1178 RelocationPacker packer; | 1176 RelocationPacker packer; |
1179 packer.UnpackRelativeRelocations(packed, &relative_relocations); | 1177 packer.UnpackRelativeRelocations(packed, &relative_relocations); |
1180 const size_t unpacked_bytes = | 1178 const size_t unpacked_bytes = |
1181 relative_relocations.size() * sizeof(relative_relocations[0]); | 1179 relative_relocations.size() * sizeof(relative_relocations[0]); |
1182 LOG(INFO) << "Unpacked relative: " << unpacked_bytes << " bytes"; | 1180 LOG(INFO) << "Unpacked relative: " << unpacked_bytes << " bytes"; |
1183 | 1181 |
1184 // Retrieve the current dynamic relocations section data. | 1182 // Retrieve the current dynamic relocations section data. |
1185 data = GetSectionData(relocations_section_); | 1183 Elf_Data* data = GetSectionData(relocations_section_); |
1186 | 1184 |
1187 // Interpret data as relocations. | 1185 // Interpret data as relocations. |
1188 const Rel* relocations_base = reinterpret_cast<Rel*>(data->d_buf); | 1186 const Rel* relocations_base = reinterpret_cast<Rel*>(data->d_buf); |
1189 std::vector<Rel> relocations( | 1187 std::vector<Rel> relocations( |
1190 relocations_base, | 1188 relocations_base, |
1191 relocations_base + data->d_size / sizeof(relocations[0])); | 1189 relocations_base + data->d_size / sizeof(relocations[0])); |
1192 | 1190 |
1193 std::vector<Rel> other_relocations; | 1191 std::vector<Rel> other_relocations; |
1194 size_t padding = 0; | 1192 size_t padding = 0; |
1195 | 1193 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1227 // relocations followed by other relocations. This is the usual order in | 1225 // relocations followed by other relocations. This is the usual order in |
1228 // which we find them after linking, so this action will normally put the | 1226 // which we find them after linking, so this action will normally put the |
1229 // entire dynamic relocations section back to its pre-split-and-packed state. | 1227 // entire dynamic relocations section back to its pre-split-and-packed state. |
1230 relocations.assign(relative_relocations.begin(), relative_relocations.end()); | 1228 relocations.assign(relative_relocations.begin(), relative_relocations.end()); |
1231 relocations.insert(relocations.end(), | 1229 relocations.insert(relocations.end(), |
1232 other_relocations.begin(), other_relocations.end()); | 1230 other_relocations.begin(), other_relocations.end()); |
1233 const void* section_data = &relocations[0]; | 1231 const void* section_data = &relocations[0]; |
1234 const size_t bytes = relocations.size() * sizeof(relocations[0]); | 1232 const size_t bytes = relocations.size() * sizeof(relocations[0]); |
1235 LOG(INFO) << "Total : " << relocations.size() << " entries"; | 1233 LOG(INFO) << "Total : " << relocations.size() << " entries"; |
1236 ResizeSection<Rel>(elf_, relocations_section_, bytes); | 1234 ResizeSection<Rel>(elf_, relocations_section_, bytes); |
1237 RewriteSectionData(data, section_data, bytes); | 1235 RewriteSectionData(relocations_section_, section_data, bytes); |
1238 | 1236 |
1239 // Nearly empty the current packed android relocations section. Leaves a | 1237 // Nearly empty the current packed android relocations section. Leaves a |
1240 // four-byte stub so that some data remains allocated to the section. | 1238 // four-byte stub so that some data remains allocated to the section. |
1241 // This is a convenience which allows us to re-pack this file again without | 1239 // This is a convenience which allows us to re-pack this file again without |
1242 // having to remove the section and then add a new small one with objcopy. | 1240 // having to remove the section and then add a new small one with objcopy. |
1243 // The way we resize sections relies on there being some data in a section. | 1241 // The way we resize sections relies on there being some data in a section. |
1244 data = GetSectionData(android_relocations_section_); | |
1245 ResizeSection<Rel>( | 1242 ResizeSection<Rel>( |
1246 elf_, android_relocations_section_, sizeof(kStubIdentifier)); | 1243 elf_, android_relocations_section_, sizeof(kStubIdentifier)); |
1247 RewriteSectionData(data, &kStubIdentifier, sizeof(kStubIdentifier)); | 1244 RewriteSectionData( |
| 1245 android_relocations_section_, &kStubIdentifier, sizeof(kStubIdentifier)); |
1248 | 1246 |
1249 // Rewrite .dynamic to remove two tags describing packed android relocations. | 1247 // Rewrite .dynamic to remove two tags describing packed android relocations. |
1250 data = GetSectionData(dynamic_section_); | 1248 data = GetSectionData(dynamic_section_); |
1251 const ELF::Dyn* dynamic_base = reinterpret_cast<ELF::Dyn*>(data->d_buf); | 1249 const ELF::Dyn* dynamic_base = reinterpret_cast<ELF::Dyn*>(data->d_buf); |
1252 std::vector<ELF::Dyn> dynamics( | 1250 std::vector<ELF::Dyn> dynamics( |
1253 dynamic_base, | 1251 dynamic_base, |
1254 dynamic_base + data->d_size / sizeof(dynamics[0])); | 1252 dynamic_base + data->d_size / sizeof(dynamics[0])); |
1255 RemoveDynamicEntry(DT_ANDROID_REL_OFFSET, &dynamics); | 1253 RemoveDynamicEntry(DT_ANDROID_REL_OFFSET, &dynamics); |
1256 RemoveDynamicEntry(DT_ANDROID_REL_SIZE, &dynamics); | 1254 RemoveDynamicEntry(DT_ANDROID_REL_SIZE, &dynamics); |
1257 const void* dynamics_data = &dynamics[0]; | 1255 const void* dynamics_data = &dynamics[0]; |
1258 const size_t dynamics_bytes = dynamics.size() * sizeof(dynamics[0]); | 1256 const size_t dynamics_bytes = dynamics.size() * sizeof(dynamics[0]); |
1259 RewriteSectionData(data, dynamics_data, dynamics_bytes); | 1257 RewriteSectionData(dynamic_section_, dynamics_data, dynamics_bytes); |
1260 | 1258 |
1261 Flush(); | 1259 Flush(); |
1262 return true; | 1260 return true; |
1263 } | 1261 } |
1264 | 1262 |
1265 // Flush rewritten shared object file data. | 1263 // Flush rewritten shared object file data. |
1266 void ElfFile::Flush() { | 1264 void ElfFile::Flush() { |
1267 // Flag all ELF data held in memory as needing to be written back to the | 1265 // Flag all ELF data held in memory as needing to be written back to the |
1268 // file, and tell libelf that we have controlled the file layout. | 1266 // file, and tell libelf that we have controlled the file layout. |
1269 elf_flagelf(elf_, ELF_C_SET, ELF_F_DIRTY); | 1267 elf_flagelf(elf_, ELF_C_SET, ELF_F_DIRTY); |
1270 elf_flagelf(elf_, ELF_C_SET, ELF_F_LAYOUT); | 1268 elf_flagelf(elf_, ELF_C_SET, ELF_F_LAYOUT); |
1271 | 1269 |
1272 // Write ELF data back to disk. | 1270 // Write ELF data back to disk. |
1273 const off_t file_bytes = elf_update(elf_, ELF_C_WRITE); | 1271 const off_t file_bytes = elf_update(elf_, ELF_C_WRITE); |
1274 CHECK(file_bytes > 0); | 1272 CHECK(file_bytes > 0); |
1275 VLOG(1) << "elf_update returned: " << file_bytes; | 1273 VLOG(1) << "elf_update returned: " << file_bytes; |
1276 | 1274 |
1277 // Clean up libelf, and truncate the output file to the number of bytes | 1275 // Clean up libelf, and truncate the output file to the number of bytes |
1278 // written by elf_update(). | 1276 // written by elf_update(). |
1279 elf_end(elf_); | 1277 elf_end(elf_); |
1280 elf_ = NULL; | 1278 elf_ = NULL; |
1281 const int truncate = ftruncate(fd_, file_bytes); | 1279 const int truncate = ftruncate(fd_, file_bytes); |
1282 CHECK(truncate == 0); | 1280 CHECK(truncate == 0); |
1283 } | 1281 } |
1284 | 1282 |
1285 } // namespace relocation_packer | 1283 } // namespace relocation_packer |
OLD | NEW |