1 /*
2  * Copyright (C) 2022 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 #pragma once
18 
19 #include <stdio.h>
20 
21 #include <memory>
22 #include <string>
23 
24 #include <android-base/logging.h>
25 
26 #include "environment.h"
27 
28 namespace simpleperf {
29 
30 class TempSymFile {
31  public:
Create(std::string && path,bool remove_in_destructor)32   static std::unique_ptr<TempSymFile> Create(std::string&& path, bool remove_in_destructor) {
33     FILE* fp = fopen(path.data(), "web");
34     if (fp == nullptr) {
35       PLOG(ERROR) << "failed to create " << path;
36       return nullptr;
37     }
38     if (remove_in_destructor) {
39       ScopedTempFiles::RegisterTempFile(path);
40     }
41     std::unique_ptr<TempSymFile> symfile(new TempSymFile(std::move(path), fp));
42     if (!symfile->WriteHeader()) {
43       return nullptr;
44     }
45     return symfile;
46   }
47 
WriteEntry(const char * data,size_t size)48   bool WriteEntry(const char* data, size_t size) {
49     if (fwrite(data, size, 1, fp_.get()) != 1) {
50       PLOG(ERROR) << "failed to write to " << path_;
51       return false;
52     }
53     file_offset_ += size;
54     need_flush_ = true;
55     return true;
56   }
57 
Flush()58   bool Flush() {
59     if (need_flush_) {
60       if (fflush(fp_.get()) != 0) {
61         PLOG(ERROR) << "failed to flush " << path_;
62         return false;
63       }
64       need_flush_ = false;
65     }
66     return true;
67   }
68 
GetPath()69   const std::string& GetPath() const { return path_; }
GetOffset()70   uint64_t GetOffset() const { return file_offset_; }
71 
72  private:
TempSymFile(std::string && path,FILE * fp)73   TempSymFile(std::string&& path, FILE* fp) : path_(std::move(path)), fp_(fp, fclose) {}
74 
WriteHeader()75   bool WriteHeader() {
76     char magic[8] = "JIT_SYM";
77     static_assert(sizeof(magic) == 8);
78     if (fwrite(magic, sizeof(magic), 1, fp_.get()) != 1) {
79       PLOG(ERROR) << "failed to write to " << path_;
80       return false;
81     }
82     file_offset_ = sizeof(magic);
83     return true;
84   }
85 
86   const std::string path_;
87   std::unique_ptr<FILE, decltype(&fclose)> fp_;
88   uint64_t file_offset_ = 0;
89   bool need_flush_ = false;
90 };
91 
92 }  // namespace simpleperf
93