summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJordi Olivares Provencio <jordi.olivares-provencio@mongodb.com>2022-09-19 13:25:33 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-09-19 13:55:23 +0000
commit0a4a4a8239993fe2203059b3d5228dfcef57b1c3 (patch)
tree3be8a9772a30b9cae5add7dc633bc3d644357271 /src
parentfc98fdb6d67eb51112fcb72d82a561d580ee085a (diff)
downloadmongo-0a4a4a8239993fe2203059b3d5228dfcef57b1c3.tar.gz
SERVER-69365 Support updating indices in updateWithDamages
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/catalog/SConscript1
-rw-r--r--src/mongo/db/catalog/collection.h21
-rw-r--r--src/mongo/db/catalog/collection_impl.cpp48
-rw-r--r--src/mongo/db/catalog/collection_impl.h17
-rw-r--r--src/mongo/db/catalog/collection_mock.h14
-rw-r--r--src/mongo/db/catalog/collection_test.cpp102
-rw-r--r--src/mongo/db/exec/update_stage.cpp13
-rw-r--r--src/mongo/db/repl/storage_timestamp_test.cpp4
-rw-r--r--src/mongo/dbtests/multikey_paths_test.cpp55
-rw-r--r--src/third_party/unwind/dist/include/libunwind-x86.h174
10 files changed, 322 insertions, 127 deletions
diff --git a/src/mongo/db/catalog/SConscript b/src/mongo/db/catalog/SConscript
index f8f638d92e5..1a0683feb93 100644
--- a/src/mongo/db/catalog/SConscript
+++ b/src/mongo/db/catalog/SConscript
@@ -650,6 +650,7 @@ if wiredtiger:
'$BUILD_DIR/mongo/db/auth/authmocks',
'$BUILD_DIR/mongo/db/catalog/collection_crud',
'$BUILD_DIR/mongo/db/commands/test_commands_enabled',
+ '$BUILD_DIR/mongo/db/index/index_access_method',
'$BUILD_DIR/mongo/db/index_builds_coordinator_mongod',
'$BUILD_DIR/mongo/db/multitenancy',
'$BUILD_DIR/mongo/db/op_observer/op_observer',
diff --git a/src/mongo/db/catalog/collection.h b/src/mongo/db/catalog/collection.h
index 57507888829..cec7b61d470 100644
--- a/src/mongo/db/catalog/collection.h
+++ b/src/mongo/db/catalog/collection.h
@@ -367,19 +367,20 @@ public:
virtual bool updateWithDamagesSupported() const = 0;
/**
- * Not allowed to modify indexes.
* Illegal to call if updateWithDamagesSupported() returns false.
* Sets 'args.updatedDoc' to the updated version of the document with damages applied, on
* success.
- * @return the contents of the updated record.
- */
- virtual StatusWith<RecordData> updateDocumentWithDamages(
- OperationContext* opCtx,
- const RecordId& loc,
- const Snapshotted<RecordData>& oldRec,
- const char* damageSource,
- const mutablebson::DamageVector& damages,
- CollectionUpdateArgs* args) const = 0;
+ *
+ * Returns the contents of the updated document on success.
+ */
+ virtual StatusWith<BSONObj> updateDocumentWithDamages(OperationContext* opCtx,
+ const RecordId& loc,
+ const Snapshotted<BSONObj>& oldDoc,
+ const char* damageSource,
+ const mutablebson::DamageVector& damages,
+ bool indexesAffected,
+ OpDebug* opDebug,
+ CollectionUpdateArgs* args) const = 0;
// -----------
diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp
index eb0ed37f2aa..ee764810669 100644
--- a/src/mongo/db/catalog/collection_impl.cpp
+++ b/src/mongo/db/catalog/collection_impl.cpp
@@ -1012,22 +1012,24 @@ bool CollectionImpl::updateWithDamagesSupported() const {
return _shared->_recordStore->updateWithDamagesSupported();
}
-StatusWith<RecordData> CollectionImpl::updateDocumentWithDamages(
+StatusWith<BSONObj> CollectionImpl::updateDocumentWithDamages(
OperationContext* opCtx,
const RecordId& loc,
- const Snapshotted<RecordData>& oldRec,
+ const Snapshotted<BSONObj>& oldDoc,
const char* damageSource,
const mutablebson::DamageVector& damages,
+ bool indexesAffected,
+ OpDebug* opDebug,
CollectionUpdateArgs* args) const {
dassert(opCtx->lockState()->isCollectionLockedForMode(ns(), MODE_IX));
- invariant(oldRec.snapshotId() == opCtx->recoveryUnit()->getSnapshotId());
+ invariant(oldDoc.snapshotId() == opCtx->recoveryUnit()->getSnapshotId());
invariant(updateWithDamagesSupported());
// For in-place updates we need to grab an owned copy of the pre-image doc if pre-image
// recording is enabled and we haven't already set the pre-image due to this update being
// a retryable findAndModify or a possible update to the shard key.
if (!args->preImageDoc && isChangeStreamPreAndPostImagesEnabled()) {
- args->preImageDoc = oldRec.value().toBson().getOwned();
+ args->preImageDoc = oldDoc.value().getOwned();
}
OplogUpdateEntryArgs onUpdateArgs(args, ns(), _uuid);
const bool setNeedsRetryImageOplogField =
@@ -1050,17 +1052,45 @@ StatusWith<RecordData> CollectionImpl::updateDocumentWithDamages(
invariant(!(isRetryableWrite(opCtx) && setNeedsRetryImageOplogField));
}
- auto newRecStatus =
- _shared->_recordStore->updateWithDamages(opCtx, loc, oldRec.value(), damageSource, damages);
+ RecordData oldRecordData(oldDoc.value().objdata(), oldDoc.value().objsize());
+ StatusWith<BSONObj> newDocStatus =
+ _shared->_recordStore->updateWithDamages(opCtx, loc, oldRecordData, damageSource, damages)
+ .transform(
+ [](RecordData&& recordData) { return recordData.releaseToBson().getOwned(); });
- if (newRecStatus.isOK()) {
- args->updatedDoc = newRecStatus.getValue().toBson();
+ if (newDocStatus.isOK()) {
+ args->updatedDoc = newDocStatus.getValue();
args->changeStreamPreAndPostImagesEnabledForCollection =
isChangeStreamPreAndPostImagesEnabled();
+ if (indexesAffected) {
+ int64_t keysInserted = 0;
+ int64_t keysDeleted = 0;
+
+ uassertStatusOK(_indexCatalog->updateRecord(opCtx,
+ {this, CollectionPtr::NoYieldTag{}},
+ oldDoc.value(),
+ args->updatedDoc,
+ loc,
+ &keysInserted,
+ &keysDeleted));
+
+ if (opDebug) {
+ opDebug->additiveMetrics.incrementKeysInserted(keysInserted);
+ opDebug->additiveMetrics.incrementKeysDeleted(keysDeleted);
+ // 'opDebug' may be deleted at rollback time in case of multi-document transaction.
+ if (!opCtx->inMultiDocumentTransaction()) {
+ opCtx->recoveryUnit()->onRollback([opDebug, keysInserted, keysDeleted]() {
+ opDebug->additiveMetrics.incrementKeysInserted(-keysInserted);
+ opDebug->additiveMetrics.incrementKeysDeleted(-keysDeleted);
+ });
+ }
+ }
+ }
+
opCtx->getServiceContext()->getOpObserver()->onUpdate(opCtx, onUpdateArgs);
}
- return newRecStatus;
+ return newDocStatus;
}
bool CollectionImpl::isTemporary() const {
diff --git a/src/mongo/db/catalog/collection_impl.h b/src/mongo/db/catalog/collection_impl.h
index c125f4cfbaf..0594d3c289e 100644
--- a/src/mongo/db/catalog/collection_impl.h
+++ b/src/mongo/db/catalog/collection_impl.h
@@ -204,18 +204,19 @@ public:
bool updateWithDamagesSupported() const final;
/**
- * Not allowed to modify indexes.
* Illegal to call if updateWithDamagesSupported() returns false.
* Sets 'args.updatedDoc' to the updated version of the document with damages applied, on
* success.
- * @return the contents of the updated record.
+ * Returns the contents of the updated document.
*/
- StatusWith<RecordData> updateDocumentWithDamages(OperationContext* opCtx,
- const RecordId& loc,
- const Snapshotted<RecordData>& oldRec,
- const char* damageSource,
- const mutablebson::DamageVector& damages,
- CollectionUpdateArgs* args) const final;
+ StatusWith<BSONObj> updateDocumentWithDamages(OperationContext* opCtx,
+ const RecordId& loc,
+ const Snapshotted<BSONObj>& oldDoc,
+ const char* damageSource,
+ const mutablebson::DamageVector& damages,
+ bool indexesAffected,
+ OpDebug* opDebug,
+ CollectionUpdateArgs* args) const final;
// -----------
diff --git a/src/mongo/db/catalog/collection_mock.h b/src/mongo/db/catalog/collection_mock.h
index a9dbfe10427..34e90b34d22 100644
--- a/src/mongo/db/catalog/collection_mock.h
+++ b/src/mongo/db/catalog/collection_mock.h
@@ -174,12 +174,14 @@ public:
MONGO_UNREACHABLE;
}
- StatusWith<RecordData> updateDocumentWithDamages(OperationContext* opCtx,
- const RecordId& loc,
- const Snapshotted<RecordData>& oldRec,
- const char* damageSource,
- const mutablebson::DamageVector& damages,
- CollectionUpdateArgs* args) const {
+ StatusWith<BSONObj> updateDocumentWithDamages(OperationContext* opCtx,
+ const RecordId& loc,
+ const Snapshotted<BSONObj>& oldDoc,
+ const char* damageSource,
+ const mutablebson::DamageVector& damages,
+ bool indexesAffected,
+ OpDebug* opDebug,
+ CollectionUpdateArgs* args) const {
MONGO_UNREACHABLE;
}
diff --git a/src/mongo/db/catalog/collection_test.cpp b/src/mongo/db/catalog/collection_test.cpp
index e05bec3c790..56b2b6d72f1 100644
--- a/src/mongo/db/catalog/collection_test.cpp
+++ b/src/mongo/db/catalog/collection_test.cpp
@@ -34,7 +34,10 @@
#include "mongo/db/catalog/collection_validation.h"
#include "mongo/db/catalog/collection_write_path.h"
#include "mongo/db/db_raii.h"
+#include "mongo/db/index/index_access_method.h"
#include "mongo/db/repl/storage_interface_impl.h"
+#include "mongo/db/update/document_diff_applier.h"
+#include "mongo/db/update/document_diff_calculator.h"
#include "mongo/stdx/thread.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/assert_util.h"
@@ -239,6 +242,105 @@ void CollectionTest::makeCollectionForMultikey(NamespaceString nss, StringData i
}
}
+TEST_F(CollectionTest, VerifyIndexIsUpdated) {
+ NamespaceString nss("test.t");
+ auto indexName = "myindex"_sd;
+ makeCollectionForMultikey(nss, indexName);
+
+ auto opCtx = operationContext();
+ AutoGetCollection autoColl(opCtx, nss, MODE_IX);
+ const auto& coll = autoColl.getCollection();
+
+ auto oldDoc = BSON("_id" << 1 << "a" << 1);
+ {
+ WriteUnitOfWork wuow(opCtx);
+ ASSERT_OK(
+ collection_internal::insertDocument(opCtx, coll, InsertStatement(oldDoc), nullptr));
+ wuow.commit();
+ }
+ auto idxCatalog = coll->getIndexCatalog();
+ auto idIndex = idxCatalog->findIdIndex(opCtx);
+ auto userIdx = idxCatalog->findIndexByName(opCtx, indexName);
+ auto oldRecordId = idIndex->getEntry()->accessMethod()->asSortedData()->findSingle(
+ opCtx, coll, BSON("_id" << 1));
+ auto oldIndexRecordID = userIdx->getEntry()->accessMethod()->asSortedData()->findSingle(
+ opCtx, coll, BSON("a" << 1));
+ ASSERT_TRUE(!oldRecordId.isNull());
+ ASSERT_EQ(oldRecordId, oldIndexRecordID);
+ {
+ Snapshotted<BSONObj> result;
+ ASSERT_TRUE(coll->findDoc(opCtx, oldRecordId, &result));
+ ASSERT_BSONOBJ_EQ(oldDoc, result.value());
+ }
+
+ auto newDoc = BSON("_id" << 1 << "a" << 5);
+ {
+ WriteUnitOfWork wuow(opCtx);
+ Snapshotted<BSONObj> oldSnap(opCtx->recoveryUnit()->getSnapshotId(), oldDoc);
+ CollectionUpdateArgs args;
+ coll->updateDocument(opCtx, oldRecordId, oldSnap, newDoc, true, nullptr, &args);
+ wuow.commit();
+ }
+ auto indexRecordId = userIdx->getEntry()->accessMethod()->asSortedData()->findSingle(
+ opCtx, coll, BSON("a" << 1));
+ ASSERT_TRUE(indexRecordId.isNull());
+ indexRecordId = userIdx->getEntry()->accessMethod()->asSortedData()->findSingle(
+ opCtx, coll, BSON("a" << 5));
+ ASSERT_EQ(indexRecordId, oldRecordId);
+}
+
+TEST_F(CollectionTest, VerifyIndexIsUpdatedWithDamages) {
+ NamespaceString nss("test.t");
+ auto indexName = "myindex"_sd;
+ makeCollectionForMultikey(nss, indexName);
+
+ auto opCtx = operationContext();
+ AutoGetCollection autoColl(opCtx, nss, MODE_IX);
+ const auto& coll = autoColl.getCollection();
+
+ auto oldDoc = BSON("_id" << 1 << "a" << 1 << "b"
+ << "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
+ {
+ WriteUnitOfWork wuow(opCtx);
+ ASSERT_OK(
+ collection_internal::insertDocument(opCtx, coll, InsertStatement(oldDoc), nullptr));
+ wuow.commit();
+ }
+ auto idxCatalog = coll->getIndexCatalog();
+ auto idIndex = idxCatalog->findIdIndex(opCtx);
+ auto userIdx = idxCatalog->findIndexByName(opCtx, indexName);
+ auto oldRecordId = idIndex->getEntry()->accessMethod()->asSortedData()->findSingle(
+ opCtx, coll, BSON("_id" << 1));
+ ASSERT_TRUE(!oldRecordId.isNull());
+
+ auto newDoc = BSON("_id" << 1 << "a" << 5 << "b" << 32);
+ auto diff = doc_diff::computeDiff(oldDoc, newDoc, 0, nullptr);
+ ASSERT(diff);
+ auto damagesOutput = doc_diff::computeDamages(oldDoc, diff->diff, false);
+ {
+ WriteUnitOfWork wuow(opCtx);
+ Snapshotted<BSONObj> oldSnap(opCtx->recoveryUnit()->getSnapshotId(), oldDoc);
+ CollectionUpdateArgs args;
+ auto newDocStatus = coll->updateDocumentWithDamages(opCtx,
+ oldRecordId,
+ oldSnap,
+ damagesOutput.damageSource.get(),
+ damagesOutput.damages,
+ true,
+ nullptr,
+ &args);
+ ASSERT_OK(newDocStatus);
+ ASSERT_BSONOBJ_EQ(newDoc, newDocStatus.getValue());
+ wuow.commit();
+ }
+ auto indexRecordId = userIdx->getEntry()->accessMethod()->asSortedData()->findSingle(
+ opCtx, coll, BSON("a" << 1));
+ ASSERT_TRUE(indexRecordId.isNull());
+ indexRecordId = userIdx->getEntry()->accessMethod()->asSortedData()->findSingle(
+ opCtx, coll, BSON("a" << 5));
+ ASSERT_EQ(indexRecordId, oldRecordId);
+}
+
TEST_F(CollectionTest, SetIndexIsMultikey) {
NamespaceString nss("test.t");
auto indexName = "myindex"_sd;
diff --git a/src/mongo/db/exec/update_stage.cpp b/src/mongo/db/exec/update_stage.cpp
index 0874f060fcf..a4783813bd4 100644
--- a/src/mongo/db/exec/update_stage.cpp
+++ b/src/mongo/db/exec/update_stage.cpp
@@ -294,12 +294,17 @@ BSONObj UpdateStage::transformAndUpdate(const Snapshotted<BSONObj>& oldObj,
}
WriteUnitOfWork wunit(opCtx());
- StatusWith<RecordData> newRecStatus = collection()->updateDocumentWithDamages(
- opCtx(), recordId, std::move(snap), source, _damages, &args);
+ newObj = uassertStatusOK(
+ collection()->updateDocumentWithDamages(opCtx(),
+ recordId,
+ oldObj,
+ source,
+ _damages,
+ driver->modsAffectIndices(),
+ _params.opDebug,
+ &args));
invariant(oldObj.snapshotId() == opCtx()->recoveryUnit()->getSnapshotId());
wunit.commit();
-
- newObj = uassertStatusOK(std::move(newRecStatus)).releaseToBson();
}
newRecordId = recordId;
diff --git a/src/mongo/db/repl/storage_timestamp_test.cpp b/src/mongo/db/repl/storage_timestamp_test.cpp
index d0fa308e2a6..616a79dec67 100644
--- a/src/mongo/db/repl/storage_timestamp_test.cpp
+++ b/src/mongo/db/repl/storage_timestamp_test.cpp
@@ -3362,14 +3362,12 @@ TEST_F(RetryableFindAndModifyTest, RetryableFindAndModifyUpdateWithDamages) {
{
Snapshotted<BSONObj> objSnapshot(_opCtx->recoveryUnit()->getSnapshotId(), oldObj);
- const RecordData oldRec(objSnapshot.value().objdata(), objSnapshot.value().objsize());
- Snapshotted<RecordData> recordSnapshot(objSnapshot.snapshotId(), oldRec);
auto cursor = collection->getCursor(_opCtx);
auto record = cursor->next();
invariant(record);
WriteUnitOfWork wuow(_opCtx);
const auto statusWith = collection->updateDocumentWithDamages(
- _opCtx, record->id, std::move(recordSnapshot), source, damages, &args);
+ _opCtx, record->id, objSnapshot, source, damages, false, nullptr, &args);
wuow.commit();
ASSERT_OK(statusWith.getStatus());
}
diff --git a/src/mongo/dbtests/multikey_paths_test.cpp b/src/mongo/dbtests/multikey_paths_test.cpp
index 6e7a9e80520..1a2b7f24df4 100644
--- a/src/mongo/dbtests/multikey_paths_test.cpp
+++ b/src/mongo/dbtests/multikey_paths_test.cpp
@@ -34,6 +34,8 @@
#include "mongo/db/index/multikey_paths.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/service_context.h"
+#include "mongo/db/update/document_diff_applier.h"
+#include "mongo/db/update/document_diff_calculator.h"
#include "mongo/dbtests/dbtests.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/str.h"
@@ -267,6 +269,59 @@ TEST_F(MultikeyPathsTest, PathsUpdatedOnDocumentUpdate) {
assertMultikeyPaths(collection.getCollection(), keyPattern, {MultikeyComponents{}, {0U}});
}
+TEST_F(MultikeyPathsTest, PathsUpdatedOnDocumentUpdateWithDamages) {
+ BSONObj keyPattern = BSON("a" << 1 << "b" << 1);
+ createIndex(collection(),
+ BSON("name"
+ << "a_1_b_1"
+ << "key" << keyPattern << "v" << static_cast<int>(kIndexVersion)))
+ .transitional_ignore();
+ AutoGetCollection collection(_opCtx.get(), _nss, MODE_IX);
+
+ auto oldDoc = BSON("_id" << 0 << "a" << 5);
+ {
+ WriteUnitOfWork wuow(_opCtx.get());
+ OpDebug* const nullOpDebug = nullptr;
+ ASSERT_OK(collection_internal::insertDocument(
+ _opCtx.get(), *collection, InsertStatement(oldDoc), nullOpDebug));
+ wuow.commit();
+ }
+
+ assertMultikeyPaths(
+ collection.getCollection(), keyPattern, {MultikeyComponents{}, MultikeyComponents{}});
+
+ {
+ auto cursor = collection->getCursor(_opCtx.get());
+ auto record = cursor->next();
+ invariant(record);
+
+ auto oldDoc = collection->docFor(_opCtx.get(), record->id);
+ auto newDoc = BSON("_id" << 0 << "a" << 5 << "b" << BSON_ARRAY(1 << 2 << 3));
+ auto diffResult = doc_diff::computeDiff(oldDoc.value(), newDoc, 0, nullptr);
+ auto damagesOutput = doc_diff::computeDamages(oldDoc.value(), diffResult->diff, false);
+ {
+ WriteUnitOfWork wuow(_opCtx.get());
+ const bool indexesAffected = true;
+ OpDebug* opDebug = nullptr;
+ CollectionUpdateArgs args;
+ auto newDocResult =
+ collection->updateDocumentWithDamages(_opCtx.get(),
+ record->id,
+ oldDoc,
+ damagesOutput.damageSource.get(),
+ damagesOutput.damages,
+ indexesAffected,
+ opDebug,
+ &args);
+ ASSERT_TRUE(newDocResult.getValue().woCompare(newDoc) == 0);
+ ASSERT_TRUE(newDocResult.isOK());
+ wuow.commit();
+ }
+ }
+
+ assertMultikeyPaths(collection.getCollection(), keyPattern, {MultikeyComponents{}, {0U}});
+}
+
TEST_F(MultikeyPathsTest, PathsNotUpdatedOnDocumentDelete) {
BSONObj keyPattern = BSON("a" << 1 << "b" << 1);
createIndex(collection(),
diff --git a/src/third_party/unwind/dist/include/libunwind-x86.h b/src/third_party/unwind/dist/include/libunwind-x86.h
index 542c1774908..9b9de0549b7 100644
--- a/src/third_party/unwind/dist/include/libunwind-x86.h
+++ b/src/third_party/unwind/dist/include/libunwind-x86.h
@@ -30,33 +30,38 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
extern "C" {
#endif
-#include <sys/types.h>
#include <inttypes.h>
+#include <sys/types.h>
#include <ucontext.h>
-#define UNW_TARGET x86
-#define UNW_TARGET_X86 1
+#define UNW_TARGET x86
+#define UNW_TARGET_X86 1
-#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
+#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */
/* This needs to be big enough to accommodate "struct cursor", while
leaving some slack for future expansion. Changing this value will
require recompiling all users of this library. Stack allocation is
relatively cheap and unwind-state copying is relatively rare, so we
want to err on making it rather too big than too small. */
-#define UNW_TDEP_CURSOR_LEN 127
+#define UNW_TDEP_CURSOR_LEN 127
typedef uint32_t unw_word_t;
typedef int32_t unw_sword_t;
typedef union {
- struct { uint8_t b[4]; } val32;
- struct { uint8_t b[10]; } val80;
- struct { uint8_t b[16]; } val128;
+ struct {
+ uint8_t b[4];
+ } val32;
+ struct {
+ uint8_t b[10];
+ } val80;
+ struct {
+ uint8_t b[16];
+ } val128;
} unw_tdep_fpreg_t;
-typedef enum
- {
+typedef enum {
/* Note: general registers are expected to start with index 0.
This convention facilitates architecture-independent
implementation of the C++ exception handling ABI. See
@@ -72,115 +77,110 @@ typedef enum
DWARF, but that doesn't work because the libunwind requires
that the exception argument registers be consecutive, which the
wouldn't be with the DWARF numbering. */
- UNW_X86_EAX, /* scratch (exception argument 1) */
- UNW_X86_EDX, /* scratch (exception argument 2) */
- UNW_X86_ECX, /* scratch */
- UNW_X86_EBX, /* preserved */
- UNW_X86_ESI, /* preserved */
- UNW_X86_EDI, /* preserved */
- UNW_X86_EBP, /* (optional) frame-register */
- UNW_X86_ESP, /* (optional) frame-register */
- UNW_X86_EIP, /* frame-register */
- UNW_X86_EFLAGS, /* scratch (except for "direction", which is fixed */
- UNW_X86_TRAPNO, /* scratch */
+ UNW_X86_EAX, /* scratch (exception argument 1) */
+ UNW_X86_EDX, /* scratch (exception argument 2) */
+ UNW_X86_ECX, /* scratch */
+ UNW_X86_EBX, /* preserved */
+ UNW_X86_ESI, /* preserved */
+ UNW_X86_EDI, /* preserved */
+ UNW_X86_EBP, /* (optional) frame-register */
+ UNW_X86_ESP, /* (optional) frame-register */
+ UNW_X86_EIP, /* frame-register */
+ UNW_X86_EFLAGS, /* scratch (except for "direction", which is fixed */
+ UNW_X86_TRAPNO, /* scratch */
/* MMX/stacked-fp registers */
- UNW_X86_ST0, /* fp return value */
- UNW_X86_ST1, /* scratch */
- UNW_X86_ST2, /* scratch */
- UNW_X86_ST3, /* scratch */
- UNW_X86_ST4, /* scratch */
- UNW_X86_ST5, /* scratch */
- UNW_X86_ST6, /* scratch */
- UNW_X86_ST7, /* scratch */
-
- UNW_X86_FCW, /* scratch */
- UNW_X86_FSW, /* scratch */
- UNW_X86_FTW, /* scratch */
- UNW_X86_FOP, /* scratch */
- UNW_X86_FCS, /* scratch */
- UNW_X86_FIP, /* scratch */
- UNW_X86_FEA, /* scratch */
- UNW_X86_FDS, /* scratch */
+ UNW_X86_ST0, /* fp return value */
+ UNW_X86_ST1, /* scratch */
+ UNW_X86_ST2, /* scratch */
+ UNW_X86_ST3, /* scratch */
+ UNW_X86_ST4, /* scratch */
+ UNW_X86_ST5, /* scratch */
+ UNW_X86_ST6, /* scratch */
+ UNW_X86_ST7, /* scratch */
+
+ UNW_X86_FCW, /* scratch */
+ UNW_X86_FSW, /* scratch */
+ UNW_X86_FTW, /* scratch */
+ UNW_X86_FOP, /* scratch */
+ UNW_X86_FCS, /* scratch */
+ UNW_X86_FIP, /* scratch */
+ UNW_X86_FEA, /* scratch */
+ UNW_X86_FDS, /* scratch */
/* SSE registers */
- UNW_X86_XMM0_lo, /* scratch */
- UNW_X86_XMM0_hi, /* scratch */
- UNW_X86_XMM1_lo, /* scratch */
- UNW_X86_XMM1_hi, /* scratch */
- UNW_X86_XMM2_lo, /* scratch */
- UNW_X86_XMM2_hi, /* scratch */
- UNW_X86_XMM3_lo, /* scratch */
- UNW_X86_XMM3_hi, /* scratch */
- UNW_X86_XMM4_lo, /* scratch */
- UNW_X86_XMM4_hi, /* scratch */
- UNW_X86_XMM5_lo, /* scratch */
- UNW_X86_XMM5_hi, /* scratch */
- UNW_X86_XMM6_lo, /* scratch */
- UNW_X86_XMM6_hi, /* scratch */
- UNW_X86_XMM7_lo, /* scratch */
- UNW_X86_XMM7_hi, /* scratch */
-
- UNW_X86_MXCSR, /* scratch */
+ UNW_X86_XMM0_lo, /* scratch */
+ UNW_X86_XMM0_hi, /* scratch */
+ UNW_X86_XMM1_lo, /* scratch */
+ UNW_X86_XMM1_hi, /* scratch */
+ UNW_X86_XMM2_lo, /* scratch */
+ UNW_X86_XMM2_hi, /* scratch */
+ UNW_X86_XMM3_lo, /* scratch */
+ UNW_X86_XMM3_hi, /* scratch */
+ UNW_X86_XMM4_lo, /* scratch */
+ UNW_X86_XMM4_hi, /* scratch */
+ UNW_X86_XMM5_lo, /* scratch */
+ UNW_X86_XMM5_hi, /* scratch */
+ UNW_X86_XMM6_lo, /* scratch */
+ UNW_X86_XMM6_hi, /* scratch */
+ UNW_X86_XMM7_lo, /* scratch */
+ UNW_X86_XMM7_hi, /* scratch */
+
+ UNW_X86_MXCSR, /* scratch */
/* segment registers */
- UNW_X86_GS, /* special */
- UNW_X86_FS, /* special */
- UNW_X86_ES, /* special */
- UNW_X86_DS, /* special */
- UNW_X86_SS, /* special */
- UNW_X86_CS, /* special */
- UNW_X86_TSS, /* special */
- UNW_X86_LDT, /* special */
+ UNW_X86_GS, /* special */
+ UNW_X86_FS, /* special */
+ UNW_X86_ES, /* special */
+ UNW_X86_DS, /* special */
+ UNW_X86_SS, /* special */
+ UNW_X86_CS, /* special */
+ UNW_X86_TSS, /* special */
+ UNW_X86_LDT, /* special */
/* frame info (read-only) */
UNW_X86_CFA,
- UNW_X86_XMM0, /* scratch */
- UNW_X86_XMM1, /* scratch */
- UNW_X86_XMM2, /* scratch */
- UNW_X86_XMM3, /* scratch */
- UNW_X86_XMM4, /* scratch */
- UNW_X86_XMM5, /* scratch */
- UNW_X86_XMM6, /* scratch */
- UNW_X86_XMM7, /* scratch */
+ UNW_X86_XMM0, /* scratch */
+ UNW_X86_XMM1, /* scratch */
+ UNW_X86_XMM2, /* scratch */
+ UNW_X86_XMM3, /* scratch */
+ UNW_X86_XMM4, /* scratch */
+ UNW_X86_XMM5, /* scratch */
+ UNW_X86_XMM6, /* scratch */
+ UNW_X86_XMM7, /* scratch */
UNW_TDEP_LAST_REG = UNW_X86_XMM7,
UNW_TDEP_IP = UNW_X86_EIP,
UNW_TDEP_SP = UNW_X86_ESP,
UNW_TDEP_EH = UNW_X86_EAX
- }
-x86_regnum_t;
+} x86_regnum_t;
-#define UNW_TDEP_NUM_EH_REGS 2 /* eax and edx are exception args */
+#define UNW_TDEP_NUM_EH_REGS 2 /* eax and edx are exception args */
-typedef struct unw_tdep_save_loc
- {
+typedef struct unw_tdep_save_loc {
/* Additional target-dependent info on a save location. */
char unused;
- }
-unw_tdep_save_loc_t;
+} unw_tdep_save_loc_t;
/* On x86, we can directly use ucontext_t as the unwind context. */
typedef ucontext_t unw_tdep_context_t;
#include "libunwind-dynamic.h"
-typedef struct
- {
+typedef struct {
/* no x86-specific auxiliary proc-info */
char unused;
- }
-unw_tdep_proc_info_t;
+} unw_tdep_proc_info_t;
#include "libunwind-common.h"
-#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
-extern int unw_tdep_getcontext (unw_tdep_context_t *);
+#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
+extern int unw_tdep_getcontext(unw_tdep_context_t*);
-#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
-extern int unw_tdep_is_fpreg (int);
+#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
+extern int unw_tdep_is_fpreg(int);
#if defined(__cplusplus) || defined(c_plusplus)
}