(十二)自定義LLDB命令 內(nèi)存布局和SBValue

1. 自定義LLDB命令 Value和內(nèi)存

1.1 內(nèi)存布局

為了真正理解SBValue類的強(qiáng)大功能僵朗,我們將探索分配器應(yīng)用程序中三個(gè)對(duì)象的內(nèi)存布局。從一個(gè)Objective-C類開(kāi)始,然后探索一個(gè)沒(méi)有超類的Swift類保檐,最后探索一個(gè)繼承自NSObject的Swift類。

這三個(gè)類都有三個(gè)屬性,其順序如下:

  • 名為eyeColorUIColor街夭。
  • 名為firstName的字符串(string/NSString)。
  • 名為lastName的字符串(string/NSString)躏筏。

這些類的每個(gè)實(shí)例都使用相同的值初始化:

  • eyeColorUIColor.brown[UIColor brownColor]板丽。
  • firstName"Derek"@"Derek"
  • lastName"Selander"@"Selander"趁尼。
Objective-C內(nèi)存布局
@interface DSObjectiveCObject : NSObject
@property (nonatomic, strong) UIColor *eyeColor;
@property (nonatomic, strong) NSString *firstName;
@property (nonatomic, strong) NSString *lastName;
@end

@implementation DSObjectiveCObject
- (instancetype)init
{
  self = [super init];
  if (self) {
    self.eyeColor = [UIColor brownColor];
    self.firstName = @"Derek";
    self.lastName = @"Selander";
  }
  return self;
}
@end

編譯后埃碱,這個(gè)Objective-C類實(shí)際上看起來(lái)像一個(gè)C結(jié)構(gòu)。編譯器將創(chuàng)建類似于以下偽代碼的結(jié)構(gòu):

struct DSObjectiveCObject {
    Class isa;
    UIColor *eyeColor;
    NSString *firstName
    NSString *lastName
}

注意第一個(gè)參數(shù)Class isa酥泞。這就是將Objective-C類視為Objective-C類背后的魔力砚殿。isa始終是對(duì)象實(shí)例的內(nèi)存布局中的第一個(gè)值,并且是指向該對(duì)象是其實(shí)例的類的指針芝囤。之后似炎,這些屬性將按照它們?cè)谠创a中的寫(xiě)入順序添加到此結(jié)構(gòu)中。

//項(xiàng)目打印的對(duì)象
<DSObjectiveCObject: 0x600003865180>
//lldb打印的對(duì)象
(lldb) po 0x600003865180
<DSObjectiveCObject: 0x600003865180>
//將內(nèi)存地址轉(zhuǎn)成id指針凡人,再取出指針里面的值名党,我們就訪問(wèn)到了isa指針
(lldb) po *(id *)(0x600003865180)
DSObjectiveCObject

//通過(guò)內(nèi)存讀取可以獲得一樣的效果
(lldb) x/gx 0x600003865180
0x600003865180: 0x000000010c2d55d8
(lldb) po 0x000000010c2d55d8
DSObjectiveCObject

//偏移一個(gè)指針的大小,就是我們的eyeColor
(lldb) po *(id *)(0x600003865180 + 0x8)
UIExtendedSRGBColorSpace 0.6 0.4 0.2 1
//繼續(xù)偏移指針的大小挠轴,就是我們的firstName
(lldb) po *(id *)(0x600003865180 + 0x10)
Derek
//繼續(xù)偏移指針的大小传睹,就是我們的lastName
(lldb) po *(id *)(0x600003865180 + 0x18)
Selander
沒(méi)有父類的Swift內(nèi)存布局
class ASwiftClass {
  let eyeColor = UIColor.brown
  let firstName = "Derek"
  let lastName = "Selander"
  required init() { }  
}

同樣,我們可以將這個(gè)Swift類想象為一個(gè)C結(jié)構(gòu)岸晦,它與Objective-C對(duì)應(yīng)的類有一些有趣的區(qū)別:

struct ASwiftClass {
  Class isa;
  // Simplified, see "InlineRefCounts"
  // in https://github.com/apple/swift
  uintptr_t refCounts;
  
  UIColor *eyeColor;
  
  // Simplified, see "_StringGuts"
  // in https://github.com/apple/swift
  struct _StringCore {
    uintptr_t _object;  // packed bits for string type
    uintptr_t rawBits;  // raw data
  } firstName;
  
  struct _StringCore {
    uintptr_t _object;  // packed bits for string type
    uintptr_t rawBits;  // raw data
  } lastName;
}

Swift仍然將isa變量作為第一個(gè)參數(shù)欧啤。在isa變量之后,有一個(gè)8字節(jié)的變量被保留用于引用計(jì)數(shù)和對(duì)齊启上,稱為refCounts邢隧。這與典型的Objective-C對(duì)象不同,后者在此偏移處不包含此變量冈在。

接下來(lái)倒慧,一個(gè)普通的UIColor,但這就是ASwiftClass結(jié)構(gòu)完全偏離軌道的地方。

Swift字符串是一個(gè)非常有趣的“對(duì)象”纫谅。實(shí)際上炫贤,Swift字符串是ASwiftClass結(jié)構(gòu)中的一個(gè)結(jié)構(gòu)「讹酰可以將Swift字符串看作是一種外觀設(shè)計(jì)模式兰珍,它隱藏不同類型的Swift字符串類型,這取決于它們是否是硬編碼的询吴、Cocoa掠河、使用ASCII的等等。如果Swift是為32位或64位平臺(tái)編譯的猛计,則類型和布局會(huì)有所不同唠摹。為了簡(jiǎn)單起見(jiàn),只討論64位平臺(tái)有滑。

對(duì)于64位平臺(tái)跃闹,Swift字符串的內(nèi)存布局由16個(gè)字節(jié)組成,結(jié)構(gòu)布局取決于字符串的類型毛好。也就是說(shuō)望艺,首先需要確定字符串的類型,然后才能正確分析字符串的內(nèi)容肌访。

那么怎樣才能確定類型呢找默?下面的文檔摘自Swift 4.2 https://github.com/apple/swift/blob/master/stdlib/public/core/StringObject.swift

// ## _StringObject bit layout //
// x86-64 and arm64: (one 64-bit word)
// +---+---+---|---+------+------------------------------------------+
// + t | v | o | w | uuuu | payload (56 bits)                        |
// +---+---+---|---+------+------------------------------------------+
// most significant bit                         least significatn bit
//
// where t: is-a-value, i.e. a tag bit that says not to perform ARC
//       v: sub-variant bit, i.e. set for isCocoa or isSmall
//       o: is-opaque, i.e. opaque vs contiguously stored strings
//       w: width indicator bit (0: ASCII, 1: UTF-16)
//       u: unused bits
//
// payload is:
//   isNative: the native StringStorage object
//   isCocoa: the Cocoa object
//   isOpaque & !isCocoa: the _OpaqueString object
// isUnmanaged: the pointer to code units
// isSmall: opaque bits used for inline storage // TODO: use them!
//

在文檔中,t吼驶、v惩激、ow位用于幫助確定Swift字符串的類型蟹演。后面4個(gè)u位將由特定字符串類型使用风钻。也就是說(shuō),上面提到的StringCore結(jié)構(gòu)的對(duì)象變量的前4位將提供此信息酒请。

Swift字符串結(jié)構(gòu)的布局使程序匯編調(diào)用約定變得相當(dāng)有趣骡技。如果向函數(shù)傳遞字符串,它實(shí)際上將傳入兩個(gè)參數(shù)(并使用兩個(gè)寄存器)羞反,而不是指向包含這兩個(gè)參數(shù)(在一個(gè)寄存器中)的結(jié)構(gòu)的指針布朦。

像OC一樣,我們?cè)贚LDB中查看一下昼窗。

<ASwiftClass: 0x60000313bcc0>

//雖然Swift隱藏了description和debugDescription是趴,我們進(jìn)行類型轉(zhuǎn)換仍可以調(diào)用
(lldb) po 0x60000313bcc0

//在OC上下文中我們甚至可以查看它的父類,雖然我們沒(méi)有聲明
(lldb) po [0x60000313bcc0 superclass]
SwiftObject

//查看Swift類的isa指針
(lldb) po *(id *)0x60000313bcc0
Allocator.ASwiftClass

結(jié)構(gòu)中的引用計(jì)數(shù)是Swift獨(dú)有的澄惊,我們?cè)敿?xì)看看唆途。

//查看引用計(jì)數(shù)
(lldb) po *(id *)(0x60000313bcc0 + 0x8)
0x0000000000000002

(lldb) po [0x60000313bcc0 retain]
(lldb) po *(id *)(0x60000313bcc0 + 0x8)
0x0000000200000002

(lldb) po [0x60000313bcc0 release]
(lldb) po *(id *)(0x60000313bcc0 + 0x8)
0x0000000000000002

注意retain時(shí)中間的十六進(jìn)制值增加了2富雅。這個(gè)地址實(shí)際上應(yīng)該被視為兩個(gè)獨(dú)立的32位字段,而不是一個(gè)64位字段肛搬。我們接著看下面的屬性:

//和OC一樣吹榴,是我們的UIColor brown
(lldb) po *(id *)(0x60000313bcc0 + 0x10)
UIExtendedSRGBColorSpace 0.6 0.4 0.2 1

注意,我們下面開(kāi)始研究Swift的字符串滚婉,它的前4個(gè)比特決定了它的類型。

(lldb) x/gt '0x60000313bcc0 + 0x18'
0x60000313bcd8: 0b1110010100000000000000000000000000000000000000000000000000000000

看看最左邊的前四位:

  • 比特0(t):該對(duì)象不使用ARC計(jì)算引用帅刀。這解釋了為什么在前面執(zhí)行retain方法時(shí)让腹,該值最初為零。
  • 比特1(v):isSmall扣溺,在這種情況下骇窍,字符串在內(nèi)部稱為Swift small String
  • 比特2(o):實(shí)例存儲(chǔ)為不透明字符串
  • 比特3(w):未設(shè)置該值锥余,這意味著此引用使用了ASCII腹纳。

這個(gè)字符串引用是一個(gè)small String,它是一個(gè)占用少于15字節(jié)的Swift字符串驱犹。這意味著所有的內(nèi)容都可以在Swift String結(jié)構(gòu)中引用嘲恍。如果字符串大于15字節(jié),則需要一個(gè)指針來(lái)引用數(shù)據(jù)雄驹,而不只是將其打包到16字節(jié)的結(jié)構(gòu)中佃牛。關(guān)于small String,詳細(xì)信息可以在這里查看:
https://github.com/apple/swift/blob/master/stdlib/public/core/SmallString.swift

下面是UTF-8 small Swift String的簡(jiǎn)化C布局:

typedef struct {
  char spillover[7];
  char bits; // msb (tvow) bit types, lsb (uuuu) string length
  char start[8]; // start address of String
} SmallUTF8String;

在這個(gè)結(jié)構(gòu)中医舆,如果字符串的長(zhǎng)度大于8字節(jié)俘侠,則spillover是剩余的字符的開(kāi)始。還有一個(gè)bits值蔬将,它存儲(chǔ)類型和計(jì)數(shù)(較低的4位)爷速。

下面探索firstName變量的布局:

 (lldb) x/s '0x60000313bcc0 + 0x20'
0x60000313bce0: "Derek"

那它的長(zhǎng)度呢?

//對(duì)應(yīng)SmallUTF8String
//char bits; // msb (tvow) bit types, lsb (uuuu) string length
(lldb) x/gx '0x60000313bcc0 + 0x18'
0x000060000313bcd8: 0xe500000000000000
//可以多驗(yàn)證一下
(lldb) p/d *(int *)(0x60000313bcc0 + 0x18 + 7) & 0xf
(int) $10 = 5

5就是我們想要的值霞怀。

NSObject為父類的Swift內(nèi)存布局
class ASwiftNSObjectClass: NSObject {
  let eyeColor = UIColor.brown
  let firstName = "Derek"
  let lastName = "Selander"
  required override init() { }
}

那么生成的C結(jié)構(gòu)偽代碼有什么區(qū)別嗎惫东?

struct ASwiftNSObjectClass {
  Class isa;
  UIColor *eyeColor;
  struct _StringCore {
    uintptr_t _object;
    uintptr_t rawBits;
  } firstName;
  struct _StringCore {
    uintptr_t _object;
    uintptr_t rawBits;
  } lastName;
}

唯一的區(qū)別是ASwiftNSObjectClass實(shí)例在偏移量0x8處缺少refCounts變量,內(nèi)存中的其余布局將相同里烦。因?yàn)镺bjective-C有自己的retain/release實(shí)現(xiàn)凿蒜,它不同于Swift實(shí)現(xiàn)。

1.2 SBValue

SBValue負(fù)責(zé)解釋來(lái)自JIT代碼的表達(dá)式解析胁黑。把SBValue看作是一種表示废封,它允許我們像上面那樣探索對(duì)象中的成員。在SBValue實(shí)例中丧蘸,可以輕松訪問(wèn)結(jié)構(gòu)的所有成員(Objective-C或Swift類)漂洋。

SBTargetSBFrame類中怜珍,有一個(gè)名為EvaluateExpression的方法,接受Python字符串表達(dá)式并返回一個(gè)SBValue實(shí)例址儒。此外蜒秤,還有一個(gè)可選的參數(shù),用于指定希望如何解析代碼贝咙。

在么我們的在LLDB中進(jìn)行探索样悟。

(lldb) po [DSObjectiveCObject new]
<DSObjectiveCObject: 0x6000014794e0>

//用這節(jié)提到的方式執(zhí)行一次
(lldb) script lldb.frame.EvaluateExpression('[DSObjectiveCObject new]')
<lldb.SBValue; proxy of <Swig Object of type 'lldb::SBValue *' at 0x1087105a0> >

//上面的結(jié)果可能有點(diǎn)看不懂,打印一下
(lldb) script print(lldb.target.EvaluateExpression('[DSObjectiveCObject new]'))
(DSObjectiveCObject *) $2 = 0x000060000147bc60

//通過(guò)使用變量的方式
(lldb) script a = lldb.target.EvaluateExpression('[DSObjectiveCObject new]')
(lldb) script print(a)
(DSObjectiveCObject *) $3 = 0x000060000147bca0

很好庭猩,現(xiàn)在我們有一個(gè)存儲(chǔ)在aSBValue實(shí)例窟她,并且已經(jīng)知道了DSObjectiveCObject的內(nèi)存布局。

我們知道a保存的SBValue是指向DSObjectiveCObject類的指針蔼水≌鹛牵可以使用GetDescription()或更簡(jiǎn)單的SBValuedescription屬性獲取DSObjectiveCObject類的描述。同樣我們可以通過(guò)value獲得這個(gè)對(duì)象的地址趴腋。

//打印描述
(lldb) script print(a.description)
<DSObjectiveCObject: 0x60000147bca0>
//得到str類型的地址
(lldb) script print(a.value)
0x000060000147bca0
(lldb) po 0x000060000147bca0
<DSObjectiveCObject: 0x60000147bca0>

//得到signed類型的地址
(lldb) script print(a.signed)
105553137745056
(lldb) p/x 105553137745056
(long) $5 = 0x000060000147bca0
通過(guò)SBValue偏移量探索屬性
(lldb) script print(a.GetNumChildren())
4

我們可以將其理解為一個(gè)數(shù)組吊说,用一個(gè)特殊的APIGetChildAtIndex來(lái)遍歷類中的項(xiàng)目。我們得到了4优炬,因此可以在LLDB中探索索引0~3颁井。

(lldb) script print(a.GetChildAtIndex(0))
(NSObject) NSObject = {
  isa = DSObjectiveCObject
}

(lldb) script print(a.GetChildAtIndex(1))
(UICachedDeviceRGBColor *) _eyeColor = 0x00006000001de340

(lldb) script print(a.GetChildAtIndex(2))
(__NSCFConstantString *) _firstName = 0x00000001059b04b0 @"Derek"

(lldb) script print(a.GetChildAtIndex(3))
(__NSCFConstantString *) _lastName = 0x00000001059b04d0 @"Selander"

GetChildAtIndex將返回一個(gè)SBValue。因此如果需要蠢护,可以進(jìn)一步探索該對(duì)象蚤蔓。用firstName舉例:

(lldb) script print(a.GetChildAtIndex(2).description)
Derek

記住Python變量a指向?qū)ο蟮闹羔?/strong>。

(lldb) script a.size
8

輸出值表示a長(zhǎng)8字節(jié)糊余。但如果我們想知道真正的大小呢秀又?幸運(yùn)的是,SBValue有一個(gè)deref屬性贬芥,該屬性返回另一個(gè)SBValue吐辙。

(lldb) script a.deref.size
32

這將返回值32。因?yàn)樗怯?code>isa蘸劈、eyeColor昏苏、firstNamelastName構(gòu)成的,它們各自都是8字節(jié)長(zhǎng)的指針威沫。

這里有另一種方法來(lái)看看deref的屬性在做什么贤惯。探索SBValueSBType類。

(lldb) script print(a.type.name)
DSObjectiveCObject *
(lldb) script print(a.deref.type.name)
DSObjectiveCObject
通過(guò)SBValue查看原始數(shù)據(jù)

我們甚至可以使用SBValue中的data屬性查看原始數(shù)據(jù)棒掠。這個(gè)屬性是一個(gè)SBData類孵构。

//這將輸出指針的地址,注意是大端的
(lldb) script print(a.data)
a0 bc 47 01 00 60 00 00                          ..G..`..
//與上面的值進(jìn)行對(duì)比
(lldb) script print(a.value)
0x000060000147bca0

使用deref屬性可以獲取構(gòu)成這個(gè)DSObjectiveCObject的所有字節(jié)烟很。

(lldb) script print(a.deref.data)
d8 25 9b 05 01 00 00 00 40 e3 1d 00 00 60 00 00  .%......@....`..
b0 04 9b 05 01 00 00 00 d0 04 9b 05 01 00 00 00  ................

我們可以使用po *(id*) (0x000060000147bca0 + multiple_of_8)每次跳8字節(jié)查看這些屬性颈墅。

SBExpressionOptions

在討論EvaluateExpression時(shí)提到還有一個(gè)可選的參數(shù)蜡镶,它將接受SBExpressionOptions類型的實(shí)例⌒羯福可以使用此命令為JIT執(zhí)行傳遞特定選項(xiàng)官还。

(lldb) script options = lldb.SBExpressionOptions()
(lldb) script options.SetLanguage(lldb.eLanguageTypeSwift)

SBExpressionOptions有一個(gè)名為SetLanguage的方法,該方法接受lldb::LanguageType類型的LLDB模塊枚舉毒坛。LLDB作者有一個(gè)約定望伦,在枚舉、枚舉名和唯一值之前添加一個(gè)e煎殷。

這個(gè)設(shè)置選項(xiàng)意思是屡谐,現(xiàn)在將以Swift執(zhí)行代碼,而不是SBFrame的默認(rèn)語(yǔ)言類型蝌数。
現(xiàn)在告訴options變量將JIT代碼解釋為ID類型:

(lldb) script options.SetCoerceResultToId()

setConverteResultToID接受一個(gè)可選的布爾值,該值決定是否應(yīng)將其解釋為id度秘,默認(rèn)值是True顶伞。

回顧一下我們?cè)谶@里所做的:設(shè)置了使用Python API解析這個(gè)expression的選項(xiàng),而不是通過(guò)expression命令傳遞給我們的選項(xiàng)剑梳。

例如唆貌,我們現(xiàn)在聲明的SBExpressionOptions相當(dāng)于expression命令中的以下選項(xiàng):

expression -lswift -O -- your_expression_here

接下來(lái),只使用expression命令創(chuàng)建ASwiftClass的實(shí)例垢乙。如果這有效锨咙,我們將在EvaluateExpression命令中嘗試相同的表達(dá)式。在LLDB中鍵入以下內(nèi)容:

(lldb) e -lswift -O -- ASwiftClass()
error: <EXPR>:3:1: error: use of unresolved identifier 'ASwiftClass'
ASwiftClass()
^~~~~~~~~~~

我們需要導(dǎo)入Allocator模塊才能使Swift在調(diào)試器正確運(yùn)行追逮。

(lldb) e -lswift -- import Allocator
(lldb) e -lswift -O -- ASwiftClass()
<ASwiftClass: 0x60000238f500>

下面我們用EvaluateExpression再來(lái)一次酪刀。

(lldb) script b = lldb.target.EvaluateExpression('ASwiftClass()', options)

(lldb) script print(b.description)
<ASwiftClass: 0x6000023f4b40>

注意:值得指出的是,SBValue的一些特性在Swift中不能很好地發(fā)揮作用钮孵。例如骂倘,使用deref或address_of屬性解引用Swift對(duì)象將無(wú)法正常工作。通過(guò)將指針強(qiáng)制轉(zhuǎn)換為SwiftObject巴席,可以將此指針強(qiáng)制為Objective-C引用历涝,然后一切都將正常工作。

通過(guò)變量名解引用SBValue中的值

SBValue通過(guò)GetChildAtIndex引用子SBValues是一種非常簡(jiǎn)單的導(dǎo)航到內(nèi)存中對(duì)象的方法漾唉。如果這個(gè)類的作者在eyeColor之前添加了一個(gè)屬性荧库,在遍歷這個(gè)SBValue時(shí)完全破壞了偏移邏輯,會(huì)怎么樣赵刑?

幸運(yùn)的是分衫,SBValue還有另一個(gè)方法可以按名稱而不是偏移量引用實(shí)例變量:GetValueForExpressionPath

(lldb) script print(b.GetValueForExpressionPath('.firstName'))
(String) firstName = "Derek"

那如何獲得子SBValues的名稱呢般此?如果我們不知道子SBValue的名稱丐箩,可以使用GetChildAtIndex找到子SBValue摇邦,然后對(duì)該子SBValue使用name屬性。
例如屎勘,如果我不知道在b中找到的UIColor屬性的名稱施籍,我可以執(zhí)行以下操作:

(lldb) script print(b)
(Allocator.ASwiftClass) $R4 = 0x00006000023f4b40 {
  eyeColor = 0x000060000238f540 {
    ObjectiveC.NSObject = {}
  }
  firstName = "Derek"
  lastName = "Selander"
}

(lldb) script print(b.GetChildAtIndex(0))
(UIColor) eyeColor = 0x000060000238f540 {
  baseUIDeviceRGBColor@0 = {
    baseUIColor@0 = {
      baseNSObject@0 = {
        isa = UICachedDeviceRGBColor
      }
      _systemColorName = 0x000060000363ff80 "brownColor"
      _cachedStyleString = nil
    }
    redComponent = 0.59999999999999998
    greenComponent = 0.40000000000000002
    blueComponent = 0.20000000000000001
    alphaComponent = 1
    _cachedColor = 0x0000000000000000
  }
}

(lldb) script print(b.GetChildAtIndex(0).name)
eyeColor

(lldb) script print(b.GetValueForExpressionPath('.eyeColor'))
(UIColor) eyeColor = 0x000060000238f540 {
  ObjectiveC.NSObject = {}
}

(lldb) script print(b.GetValueForExpressionPath('.eyeColor').description)
UIExtendedSRGBColorSpace 0.6 0.4 0.2 1

1.3 lldb.value

最后一件很酷的事情是創(chuàng)建一個(gè)Python引用,它包含SBValue的屬性作為Python對(duì)象的屬性概漱〕笊鳎可以把它看作一個(gè)對(duì)象,通過(guò)它可以使用Python屬性而不是字符串引用變量瓤摧。

(lldb) script c = lldb.value(b)

(lldb) script print(c.firstName)
(String) firstName = "Derek"

(lldb) script print(c.firstName.sbvalue.description)
"Derek"

上面的代碼將創(chuàng)建一個(gè)特殊LLDB Python對(duì)象「土眩現(xiàn)在我們可以像引用普通對(duì)象一樣引用它的實(shí)例變量。我們還可以把它的子對(duì)象轉(zhuǎn)回SBValue照弥。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末腻异,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子这揣,更是在濱河造成了極大的恐慌悔常,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件给赞,死亡現(xiàn)場(chǎng)離奇詭異机打,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)片迅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)残邀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人柑蛇,你說(shuō)我怎么就攤上這事芥挣。” “怎么了耻台?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵九秀,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我粘我,道長(zhǎng)鼓蜒,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任征字,我火速辦了婚禮都弹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘匙姜。我一直安慰自己畅厢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布氮昧。 她就那樣靜靜地躺著框杜,像睡著了一般浦楣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上咪辱,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天振劳,我揣著相機(jī)與錄音,去河邊找鬼油狂。 笑死历恐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的专筷。 我是一名探鬼主播弱贼,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼磷蛹!你這毒婦竟也來(lái)了吮旅?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤味咳,失蹤者是張志新(化名)和其女友劉穎庇勃,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體莺葫,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年枪眉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了捺檬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡贸铜,死狀恐怖堡纬,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蒿秦,我是刑警寧澤烤镐,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站棍鳖,受9級(jí)特大地震影響炮叶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜渡处,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一镜悉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧医瘫,春花似錦侣肄、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)吼具。三九已至,卻和暖如春矩距,著一層夾襖步出監(jiān)牢的瞬間拗盒,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工剩晴, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留锣咒,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓赞弥,卻偏偏與公主長(zhǎng)得像毅整,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子绽左,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容