blob: 2d8f05eebce11baa978010470237fc2983dab909 [file] [log] [blame]
// Copyright 2012 Google Inc. All Rights Reserved.
//
// 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.
#include "syzygy/trace/parse/parse_utils.h"
#include "base/logging.h"
#include "syzygy/common/buffer_parser.h"
namespace trace {
namespace parser {
namespace {
using ::common::BinaryBufferReader;
bool ParseString(BinaryBufferReader* reader, std::wstring* output) {
DCHECK(reader != NULL);
const wchar_t* string = NULL;
size_t length = 0;
if (!reader->ReadString(&string, &length)) {
LOG(ERROR) << "Failed to parse string from TraceFileHeader blob.";
return false;
}
if (output != NULL)
*output = string;
return true;
}
bool ParseEnvironmentStrings(BinaryBufferReader* reader,
TraceEnvironmentStrings* env_strings) {
DCHECK(reader != NULL);
if (env_strings != NULL)
env_strings->clear();
// Parse the environment string.
size_t env_string_count = 0;
while (true) {
const wchar_t* string = NULL;
size_t length = 0;
if (!reader->ReadString(&string, &length)) {
LOG(ERROR) << "Failed to parse environment strings from TraceFileHeader.";
return false;
}
if (length == 0 && env_string_count > 0)
return true;
// Parse this environment string by splitting it at the first '=' sign.
if (env_strings != NULL) {
// If we don't find a '=' we assume the whole thing is a key. This is
// actually strictly invalid, but no harm done.
const wchar_t* split = ::wcschr(string, L'=');
if (split != NULL) {
env_strings->push_back(std::make_pair(
std::wstring(string, split - string),
std::wstring(split + 1)));
} else {
env_strings->push_back(std::make_pair(std::wstring(string),
std::wstring()));
}
}
++env_string_count;
}
}
} // namespace
bool ParseEnvironmentStrings(const wchar_t* env_string,
TraceEnvironmentStrings* env_strings) {
DCHECK(env_string != NULL);
DCHECK(env_strings != NULL);
// Search for the double zero termination.
size_t i = 2;
while (true) {
if (env_string[i - 2] == 0 && env_string[i - 1] == 0)
break;
++i;
}
BinaryBufferReader reader(env_string, sizeof(env_string[0]) * i);
return ParseEnvironmentStrings(&reader, env_strings);
}
bool ParseTraceFileHeaderBlob(const TraceFileHeader& header,
std::wstring* module_path,
std::wstring* command_line,
TraceEnvironmentStrings* env_strings) {
if (header.header_size < offsetof(TraceFileHeader, blob_data)) {
LOG(ERROR) << "Invalid header size.";
return false;
}
size_t blob_length = header.header_size -
offsetof(TraceFileHeader, blob_data);
BinaryBufferReader reader(header.blob_data, blob_length);
if (!ParseString(&reader, module_path))
return false;
if (!ParseString(&reader, command_line))
return false;
if (!ParseEnvironmentStrings(&reader, env_strings))
return false;
if (reader.RemainingBytes() > 0) {
LOG(ERROR) << "TraceFileHeader blob contains extra data.";
return false;
}
return true;
}
} // namespace parser
} // namespace trace