Skip to content

Commit 349eede

Browse files
fesealivg
authored andcommitted
metaframe (#7)
* updated readme with build and install instructions * nicer * fixed repo link * x86_64 arch detection fix * Trace container with meta information. It's pull request must be merget with pull request bpt-trace-PR to bap-pintrace repository. * Support streams. This patch adds support for non-seekable devices. It also cleans the code and simplifies the implementation. 1. Removed any actions from the destructor. A finish member-function must be called. 2. Removed an overload for a container, there is no need to bloat the interface. 3. Header is initialized at the creation time. 4. Removed unnecessary instance variables and member functions. The seek function is no longer called without a purpose. At the finish procedure, if the device is seekable, we're storing the table of contents and update an offset in the header. Otherwise, we just skip it. * finish the trace in the copytrace. As now autofinish is disabled.
1 parent 3c29b4f commit 349eede

File tree

6 files changed

+94
-139
lines changed

6 files changed

+94
-139
lines changed

libtrace/src/copytrace.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ int main(int argc, char **argv) {
2525
std::string dstfile(argv[2]);
2626

2727
TraceContainerReader r(srcfile);
28-
TraceContainerWriter w(dstfile, r.get_arch(), r.get_machine(), r.get_frames_per_toc_entry(), true);
28+
TraceContainerWriter w(dstfile, r.get_arch(), r.get_machine(), r.get_frames_per_toc_entry());
2929

3030
copy_all(r, w);
31+
w.finish();
3132
}

libtrace/src/trace.container.cpp

Lines changed: 60 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -23,133 +23,92 @@ typedef off_t traceoff_t;
2323

2424
namespace SerializedTrace {
2525

26-
TraceContainerWriter::TraceContainerWriter(std::string filename,
27-
frame_architecture arch,
28-
uint64_t machine,
29-
uint64_t frames_per_toc_entry_in,
30-
bool auto_finish_in) throw (TraceException)
31-
: num_frames (0),
32-
frames_per_toc_entry (frames_per_toc_entry_in),
33-
arch (arch),
34-
mach (machine),
35-
auto_finish (auto_finish_in),
36-
is_finished (false)
37-
{
38-
ofs = fopen(filename.c_str(), "wb");
39-
if (!ofs) { throw (TraceException("Unable to open trace file for writing")); }
40-
SEEK(ofs, first_frame_offset);
26+
FILE *open_trace(const std::string& filename,
27+
frame_architecture arch,
28+
uint64_t machine,
29+
uint64_t trace_version) {
30+
FILE *ofs = fopen(filename.c_str(), "wb");
31+
if (!ofs) throw TraceException("Unable to open trace file for writing");
32+
int64_t toc_off = 0LL, toc_num_frames = 0LL;
33+
34+
WRITE(magic_number);
35+
WRITE(trace_version);
36+
uint64_t archt = (uint64_t) arch;
37+
WRITE(archt);
38+
WRITE(machine);
39+
WRITE(toc_num_frames);
40+
WRITE(toc_off);
41+
return ofs;
4142
}
4243

43-
TraceContainerWriter::~TraceContainerWriter(void) throw () {
4444

45-
/** Call finish if it has not been called already ANd if
46-
auto_finish is set. */
47-
if (!is_finished && auto_finish) {
48-
try {
49-
finish();
50-
}
51-
catch (std::exception const &e) {
52-
std::cerr << "Exception " << e.what() << " occured during TraceContainerWriter's auto-finish" << std::endl;
53-
}
45+
TraceContainerWriter::TraceContainerWriter(const std::string& filename,
46+
frame_architecture arch,
47+
uint64_t machine,
48+
uint64_t frames_per_toc_entry_in)
49+
throw (TraceException)
50+
: num_frames (0)
51+
, frames_per_toc_entry (frames_per_toc_entry_in)
52+
, ofs(open_trace(filename,arch,machine,1LL)) {}
53+
54+
TraceContainerWriter::TraceContainerWriter(const std::string& filename,
55+
const meta_frame& meta,
56+
frame_architecture arch,
57+
uint64_t machine,
58+
uint64_t frames_per_toc_entry_in)
59+
throw (TraceException)
60+
: num_frames (0)
61+
, frames_per_toc_entry (frames_per_toc_entry_in)
62+
, ofs(open_trace(filename,arch,machine,2LL)) {
63+
std::string meta_data;
64+
if (!(meta.SerializeToString(&meta_data))) {
65+
throw TraceException("Unable to serialize meta frame to ostream");
66+
}
67+
68+
uint64_t meta_size = meta_data.length();
69+
WRITE(meta_size);
70+
if (fwrite(meta_data.c_str(), 1, meta_size, ofs) != meta_size) {
71+
throw (TraceException("Unable to write meta frame to trace file"));
5472
}
5573
}
5674

57-
void TraceContainerWriter::add(frame &f) throw (TraceException) {
58-
/* Is is time for a toc entry? */
75+
void TraceContainerWriter::add(const frame &f) throw (TraceException) {
5976
if (num_frames > 0 && (num_frames % frames_per_toc_entry) == 0) {
60-
/* Yes. Add the file offset where we will insert this frame to
61-
toc. */
6277
toc.push_back(TELL(ofs));
6378
}
64-
6579
num_frames++;
6680

67-
/* Serialize to string so we can get the length. */
6881
std::string s;
6982
if (!(f.SerializeToString(&s))) {
7083
throw (TraceException("Unable to serialize frame to ostream"));
7184
}
72-
73-
/* Write the length before the frame. */
7485
uint64_t len = s.length();
75-
if (len == 0) {
76-
throw (TraceException("Attempt to add zero-length frame to trace"));
77-
}
7886
WRITE(len);
79-
80-
/* Write the frame. */
81-
traceoff_t old_offset = TELL(ofs);
82-
if (old_offset == -1) {
83-
throw (TraceException("Unable to determine the current offset in the trace"));
84-
}
85-
8687
if (fwrite(s.c_str(), 1, len, ofs) != len) {
8788
throw (TraceException("Unable to write frame to trace file"));
8889
}
89-
90-
/* Double-check our size. */
91-
assert ((uint64_t)old_offset + len == (uint64_t)TELL(ofs));
9290
}
9391

94-
void TraceContainerWriter::finish(void) throw (TraceException) {
95-
if (is_finished) {
96-
throw (TraceException("finish called twice"));
97-
}
98-
99-
/* Save the offset where we will write the toc. */
92+
void TraceContainerWriter::finish() {
10093
uint64_t toc_offset = TELL(ofs);
101-
if (toc_offset == -1) {
102-
throw (TraceException("Unable to determine the current offset in the trace"));
103-
}
104-
105-
/* Make sure the toc is the right size. */
106-
assert ((num_frames == 0) || ((num_frames - 1) / frames_per_toc_entry) == toc.size());
107-
108-
/* Write frames per toc entry. */
109-
WRITE(frames_per_toc_entry);
110-
111-
/* Write each offset to the file. */
112-
for (std::vector<uint64_t>::size_type i = 0; i < toc.size(); i++) {
113-
WRITE(toc[i]);
94+
// if we have a positive offset, then the device is seekable, so
95+
// we will write the TOC, otherwise we will skip it.
96+
if (toc_offset > 0) {
97+
assert ((num_frames - 1) / frames_per_toc_entry == toc.size());
98+
WRITE(frames_per_toc_entry);
99+
for (std::vector<uint64_t>::size_type i = 0; i < toc.size(); i++) {
100+
WRITE(toc[i]);
101+
}
102+
SEEK(ofs, num_trace_frames_offset);
103+
WRITE(num_frames);
104+
SEEK(ofs, toc_offset_offset);
105+
WRITE(toc_offset);
114106
}
115107

116-
/* Now we need to write the magic number, number of trace frames
117-
and the offset of field m at the start of the trace. */
118-
119-
/* Magic number. */
120-
SEEK(ofs, magic_number_offset);
121-
WRITE(magic_number);
122-
123-
/* Trace version. */
124-
SEEK(ofs, trace_version_offset);
125-
WRITE(out_trace_version);
126-
127-
/* CPU architecture. */
128-
SEEK(ofs, frame_arch_offset);
129-
uint64_t archt = (uint64_t) arch;
130-
WRITE(archt);
131-
132-
/* Machine type. */
133-
SEEK(ofs, frame_machine_offset);
134-
WRITE(mach);
135-
136-
/* Numer of trace frames */
137-
SEEK(ofs, num_trace_frames_offset);
138-
WRITE(num_frames);
139-
140-
/* Offset of toc. */
141-
SEEK(ofs, toc_offset_offset);
142-
WRITE(toc_offset);
143-
144-
/* Finally, close the file and mark us as finished. */
145-
if (fclose(ofs)) {
146-
throw (TraceException("Unable to close trace file"));
108+
if (fclose(ofs) != 0) {
109+
throw TraceException("Error while closing the trace");
147110
}
148-
is_finished = true;
149-
}
150-
151-
bool TraceContainerWriter::has_finished(void) throw () {
152-
return is_finished;
111+
ofs = NULL;
153112
}
154113

155114
TraceContainerReader::TraceContainerReader(std::string filename) throw (TraceException)

libtrace/src/trace.container.hpp

Lines changed: 20 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#endif
77
#include "frame_arch.h"
88

9+
10+
911
/**
1012
* A container for trace frames. We do not use protobuffers because
1113
* protobuffers can not stream output (the whole trace would have to
@@ -50,7 +52,6 @@ namespace SerializedTrace {
5052
const uint64_t magic_number = 7456879624156307493LL;
5153

5254
const uint64_t default_frames_per_toc_entry = 10000;
53-
const uint64_t default_auto_finish = false;
5455
const frame_architecture default_arch = frame_arch_i386;
5556
const uint64_t default_machine = frame_mach_i386_i386;
5657

@@ -62,9 +63,9 @@ namespace SerializedTrace {
6263
const uint64_t toc_offset_offset = 40LL;
6364
const uint64_t first_frame_offset = 48LL;
6465

65-
const uint64_t out_trace_version = 1LL;
6666
const uint64_t lowest_supported_version = 1LL;
67-
const uint64_t highest_supported_version = out_trace_version;
67+
const uint64_t highest_supported_version = 2LL;
68+
6869

6970
class TraceException: public std::exception
7071
{
@@ -93,34 +94,30 @@ namespace SerializedTrace {
9394
/** Creates a trace container writer that will output to
9495
[filename]. An entry will be added to the table of contents
9596
every [frames_per_toc_entry] entries.*/
96-
TraceContainerWriter(std::string filename,
97+
TraceContainerWriter(const std::string& filename,
9798
frame_architecture arch = default_arch,
9899
uint64_t machine = default_machine,
99-
uint64_t frames_per_toc_entry = default_frames_per_toc_entry,
100-
bool auto_finish = default_auto_finish) throw (TraceException);
100+
uint64_t frames_per_toc_entry = default_frames_per_toc_entry)
101+
throw (TraceException);
101102

102-
/** Destructor that calls finish if auto_finish is true. */
103-
~TraceContainerWriter(void) throw ();
103+
// creates a container for the second version of a protocol.
104+
TraceContainerWriter(const std::string& filename,
105+
const meta_frame& meta,
106+
frame_architecture arch = default_arch,
107+
uint64_t machine = default_machine,
108+
uint64_t frames_per_toc_entry = default_frames_per_toc_entry)
109+
throw (TraceException);
104110

105111
/** Add [frame] to the trace. */
106-
void add(frame &f) throw (TraceException);
107-
108-
/** Add all frames in container [c] to the trace. */
109-
template <typename C>
110-
void add(C &c) throw (TraceException) {
111-
for (typename C::iterator i = c.begin(); i != c.end(); i++) {
112-
add(*i);
113-
}
114-
}
112+
void add(const frame &f) throw (TraceException);
115113

116-
/** Finish the trace. Builds and writes the table of contents to
117-
* the file. Closes the file. */
118-
void finish(void) throw (TraceException);
114+
// closes the trace and underlying file stream. If the stream is
115+
// seekable, the output a table of contents and update the header
116+
// with an offset to the TOC.
117+
void finish();
119118

120-
/** Returns true iff finish() has not been called on this trace. */
121-
bool has_finished(void) throw ();
119+
private:
122120

123-
protected:
124121

125122
/* Output fstream for trace container file.
126123
*
@@ -137,17 +134,6 @@ namespace SerializedTrace {
137134
/** Frames per toc entry. */
138135
const uint64_t frames_per_toc_entry;
139136

140-
/** Architecture. */
141-
const frame_architecture arch;
142-
143-
/** Machine type. */
144-
const uint64_t mach;
145-
146-
/** Call [finish()] in destructor if not already done. */
147-
bool auto_finish;
148-
149-
/** True if [finish()] been called on this writer. */
150-
bool is_finished;
151137
};
152138

153139
class TraceContainerReader {

test/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Build tracedump utility:
2+
3+
```
4+
bapbuild tracedump.native
5+
```

test/_tags

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
true : package(bap-traces), package(cmdliner)
2+
<*.native> : package(findlib.dynload)

test/tracedump.ml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
open Core_kernel.Std
22
open Bap.Std
33
open Bap_traces.Std
4+
open Bap_plugins.Std
45
open Result
56
open Cmdliner
67

8+
79
let uri =
810
let doc = "Trace resource identifier RFC3986." in
911
let uri =
@@ -18,10 +20,11 @@ let uri =
1820
let print_error = function
1921
| `Protocol_error err -> Error.pp Format.err_formatter err
2022
| `System_error err -> prerr_string @@ Unix.error_message err
21-
| `No_provider -> prerr_string "No provider for a given URI"
22-
| `Ambiguous_uri -> prerr_string "More than one provider for a given URI"
23+
| `No_provider -> prerr_string "No provider for a given URI\n"
24+
| `Ambiguous_uri -> prerr_string "More than one provider for a given URI\n"
2325

2426
let main uri =
27+
Plugins.run ();
2528
Trace.load uri >>|
2629
(fun trace ->
2730
Trace.meta trace |>
@@ -41,7 +44,6 @@ let cmd =
4144
Term.info "tracedump" ~doc ~man
4245

4346
let () =
44-
let module M = Frame_trace_plugin in
4547
match Term.eval cmd with
4648
| `Error _ -> exit 1
4749
| `Ok result ->

0 commit comments

Comments
 (0)