1 /* 2 * Copyright 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "GcdaFile.h" 18 19 #include <inttypes.h> 20 #include <stdarg.h> 21 #include <stdint.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 26 namespace android { 27 namespace vts { 28 29 bool GcdaFile::Open() { 30 if (filename_.length() < 1) return false; 31 if (gcov_var_.file) return false; 32 33 memset(&gcov_var_, 0, sizeof(gcov_var_)); 34 gcov_var_.overread = -1u; 35 36 gcov_var_.file = fopen(filename_.c_str(), "rb"); 37 if (!gcov_var_.file) return false; 38 gcov_var_.mode = 0; 39 setbuf(gcov_var_.file, (char*)0); 40 return true; 41 } 42 43 int GcdaFile::Close() { 44 if (gcov_var_.file) { 45 fclose(gcov_var_.file); 46 gcov_var_.file = 0; 47 gcov_var_.length = 0; 48 } 49 free(gcov_var_.buffer); 50 gcov_var_.alloc = 0; 51 gcov_var_.buffer = 0; 52 gcov_var_.mode = 0; 53 return gcov_var_.error; 54 } 55 56 void GcdaFile::Sync(unsigned base, unsigned length) { 57 if (!gcov_var_.file) return; 58 59 base += length; 60 if (base - gcov_var_.start <= gcov_var_.length) { 61 gcov_var_.offset = base - gcov_var_.start; 62 } else { 63 gcov_var_.offset = gcov_var_.length = 0; 64 fseek(gcov_var_.file, base << 2, SEEK_SET); 65 gcov_var_.start = ftell(gcov_var_.file) >> 2; 66 } 67 } 68 unsigned GcdaFile::ReadStringArray(char** string_array, unsigned num_strings) { 69 unsigned i; 70 unsigned j; 71 unsigned len = 0; 72 73 for (j = 0; j < num_strings; j++) { 74 unsigned string_len = ReadUnsigned(); 75 string_array[j] = (char*)malloc(string_len * sizeof(unsigned)); // xmalloc 76 for (i = 0; i < string_len; i++) { 77 ((unsigned*)string_array[j])[i] = ReadUnsigned(); 78 } 79 len += (string_len + 1); 80 } 81 return len; 82 } 83 84 unsigned GcdaFile::ReadUnsigned() { 85 const unsigned* buffer = ReadWords(1); 86 87 if (!buffer) return 0; 88 return FromFile(buffer[0]); 89 } 90 91 void GcdaFile::Allocate(unsigned length) { 92 size_t new_size = gcov_var_.alloc; 93 94 if (!new_size) new_size = GCOV_BLOCK_SIZE; 95 new_size += length; 96 new_size *= 2; 97 gcov_var_.alloc = new_size; 98 gcov_var_.buffer = (unsigned*)realloc(gcov_var_.buffer, new_size << 2); 99 } 100 101 const unsigned* GcdaFile::ReadWords(unsigned words) { 102 const unsigned* result; 103 unsigned excess = gcov_var_.length - gcov_var_.offset; 104 105 if (!gcov_var_.file) return 0; 106 107 if (excess < words) { 108 gcov_var_.start += gcov_var_.offset; 109 memmove(gcov_var_.buffer, gcov_var_.buffer + gcov_var_.offset, excess * 4); 110 gcov_var_.offset = 0; 111 gcov_var_.length = excess; 112 if (gcov_var_.length + words > gcov_var_.alloc) { 113 Allocate(gcov_var_.length + words); 114 } 115 excess = gcov_var_.alloc - gcov_var_.length; 116 excess = fread(gcov_var_.buffer + gcov_var_.length, 1, excess << 2, 117 gcov_var_.file) >> 2; 118 gcov_var_.length += excess; 119 if (gcov_var_.length < words) { 120 gcov_var_.overread += words - gcov_var_.length; 121 gcov_var_.length = 0; 122 return 0; 123 } 124 } 125 result = &gcov_var_.buffer[gcov_var_.offset]; 126 gcov_var_.offset += words; 127 return result; 128 } 129 130 int GcdaFile::Magic(unsigned magic, unsigned expected) { 131 if (magic == expected) return 1; 132 magic = (magic >> 16) | (magic << 16); 133 magic = ((magic & 0xff00ff) << 8) | ((magic >> 8) & 0xff00ff); 134 if (magic == expected) { 135 gcov_var_.endian = 1; 136 return -1; 137 } 138 return 0; 139 } 140 141 gcov_type GcdaFile::ReadCounter() { 142 gcov_type value; 143 const unsigned* buffer = ReadWords(2); 144 if (!buffer) return 0; 145 value = FromFile(buffer[0]); 146 if (sizeof(value) > sizeof(unsigned)) { 147 value |= ((gcov_type)FromFile(buffer[1])) << 32; 148 } else if (buffer[1]) { 149 gcov_var_.error = -1; 150 } 151 return value; 152 } 153 154 void GcdaFile::WriteBlock(unsigned size) { 155 int num_words = fwrite(gcov_var_.buffer, size << 2, 1, gcov_var_.file); 156 if (num_words != 1) { 157 gcov_var_.error = 1; 158 } 159 gcov_var_.start += size; 160 gcov_var_.offset -= size; 161 } 162 163 const char* GcdaFile::ReadString() { 164 unsigned length = ReadUnsigned(); 165 if (!length) return 0; 166 return (const char*)ReadWords(length); 167 } 168 169 } // namespace vts 170 } // namespace android 171