1#import <Foundation/Foundation.h>
2
3// SourceBase will be the base class of Source.  We'll pass a Source object into a
4// function as a SourceBase, and then see if the dynamic typing can get us through the KVO
5// goo and all the way back to Source.
6
7@interface SourceBase: NSObject
8{
9    uint32_t _value;
10}
11- (SourceBase *) init;
12- (uint32_t) getValue;
13@end
14
15@implementation SourceBase
16- (SourceBase *) init
17{
18    [super init];
19    _value = 10;
20    return self;
21}
22- (uint32_t) getValue
23{
24    return _value;
25}
26@end
27
28// Source is a class that will be observed by the Observer class below.
29// When Observer sets itself up to observe this property (in initWithASource)
30// the KVO system will overwrite the "isa" pointer of the object with the "kvo'ed"
31// one.
32
33@interface Source : SourceBase
34{
35    int _property;
36}
37- (Source *) init;
38- (void) setProperty: (int) newValue;
39@end
40
41@implementation Source
42- (Source *) init
43{
44    [super init];
45    _property = 20;
46    return self;
47}
48- (void) setProperty: (int) newValue
49{
50    _property = newValue;  // This is the line in setProperty, make sure we step to here.
51}
52@end
53
54@interface SourceDerived : Source
55{
56    int _derivedValue;
57}
58- (SourceDerived *) init;
59- (uint32_t) getValue;
60@end
61
62@implementation SourceDerived
63- (SourceDerived *) init
64{
65    [super init];
66    _derivedValue = 30;
67    return self;
68}
69- (uint32_t) getValue
70{
71    return _derivedValue;
72}
73@end
74
75// Observer is the object that will watch Source and cause KVO to swizzle it...
76
77@interface Observer : NSObject
78{
79    Source *_source;
80}
81+ (Observer *) observerWithSource: (Source *) source;
82- (Observer *) initWithASource: (Source *) source;
83- (void) observeValueForKeyPath: (NSString *) path
84		       ofObject: (id) object
85			 change: (NSDictionary *) change
86			context: (void *) context;
87@end
88
89@implementation Observer
90
91+ (Observer *) observerWithSource: (Source *) inSource;
92{
93    Observer *retval;
94
95    retval = [[Observer alloc] initWithASource: inSource];
96    return retval;
97}
98
99- (Observer *) initWithASource: (Source *) source
100{
101    [super init];
102    _source = source;
103    [_source addObserver: self
104	    forKeyPath: @"property"
105	    options: (NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
106	    context: NULL];
107    return self;
108}
109
110- (void) observeValueForKeyPath: (NSString *) path
111		       ofObject: (id) object
112			 change: (NSDictionary *) change
113			context: (void *) context
114{
115    printf ("Observer function called.\n");
116    return;
117}
118@end
119
120
121int patval;          // external symbol, will not be completely stripped
122int pat(int in) {    // external symbol, will not be completely stripped
123  if (patval == 0)
124    patval = in;
125  return patval;
126}
127
128static int fooval;  // static symbol, stripped
129int foo() {         // external symbol, will not be completely stripped
130  if (fooval == 0)
131    fooval = 5;
132  return fooval;
133}
134
135int bazval = 10;   // external symbol, will not be completely stripped
136int baz () {       // external symbol, will not be completely stripped
137  return foo() + bazval;
138}
139
140static int barval = 15; // static symbol, stripped
141static int bar () {     // static symbol, stripped; __lldb_unnamed_symbol from func starts
142  return baz() + barval;
143}
144
145int calculate ()   // external symbol, will not be completely stripped
146{
147  return bar();
148}
149
150